Spring jdbc事务问题



dao层抽象

interface DaoLayer {
Long createFavouriteWidgetInfo(FavouriteWidgetInfo favouriteWidget);
}

dao层实现

class DaoLayerImpl implements DaoLayer
@Transactional
@Override
public Long createFavouriteWidgetInfo(FavouriteWidgetInfo favouriteWidget) {
Session session=sessionFactory.getCurrentSession();
Long val= (Long) session.save(favouriteWidget);
throw new NullPointerException();
//return val;
}

示例测试用例

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class Test {
@Autowired
private DaoLayer daoLayer;

@org.junit.Test
public void test()throws Exception {
FavouriteWidgetInfo info=new FavouriteWidgetInfo();
info.setGroupId(1);
info.setReportId(2);
info.setUserId(213);
info.setTenantId(21);
info.setApplicationId(2);
daoLayer.createFavouriteWidgetInfo(info);  
}

当我运行上面的测试用例的事务应该回滚,因为故意抛出NullPointerException,这是一个子类的RuntimeException,所以我的事务应该回滚,当我启用spring事务日志,我可以看到回滚日志语句,但当我查看数据库的实体是持久的

注意:-我使用SpringSessionContext类spring实现Hibernate current_session上下文,因此创建会话将由spring框架管理。

有两种可能的情况:第一个:如果mysql不支持存储引擎,它将创建一个带有MyISAM表的表,这是一个非事务性表。一般修改为InnoDB第二种:Spring的AOP(声明性事务管理)默认为未检查的异常回滚。也就是说,默认情况下,会回滚RuntimeException()异常或其子类;检查异常,也就是说,异常可以被try{}捕获,并且不会被回滚。如果使用try-catch捕获抛出的未检查异常,则该异常不在catch块中。该页面是硬编码的,spring api用于显式回滚事务,因此不会回滚事务

我猜你在控制器中使用了Exception,从服务层到控制器层,比如这个语句抛出新的异常("xxxxxxxxxxxx");事务未回滚

希望你的问题能得到解决

在您的DaoLayerImpl中,您已经在抛出NPE之前将数据保存到数据库中。如果你想为了测试而故意抛出错误,并且不想在DB中保存数据,那么从代码中删除6行,并将其放在catch块中,否则删除。

代码应该是这样的。

class DaoLayerImpl implements DaoLayer
@Transactional
@Override
public Long createFavouriteWidgetInfo(FavouriteWidgetInfo favouriteWidget) {
Session session=sessionFactory.getCurrentSession();
//Long val= (Long) session.save(favouriteWidget); //remove this line.
throw new NullPointerException();
//return val;
}

异常被忽略,因为您正在使用@Transactional注释。然后用替换注释@Transactional(rollbackFor = Exception.class)

最新更新