我创建了一个简单的 Spring 应用程序来测试 Spring 声明式事务的基础知识。根据规则,声明性事务应在 RuntimeException 的情况下回滚。但就我而言,它并没有回滚。
主要测试类有代码
public class SpringOraTest {
public static void main(String[] args) {
ApplicationContext aplctx= new
FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml");
//Call to test Declarative Transaction with Annotation
TrxHandleAnnotated prxyobj=((TrxHandleAnnotated)aplctx.getBean("dbCommandAnnotated"));
prxyobj.doTask();
}
}
TrxHandleAnnotated 类有代码:-
@Transactional
public class TrxHandleAnnotated
public void doTask(){
ApplicationContext aplctx= new
FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml");
JdbcTemplate jdbcTemplate= (JdbcTemplate)aplctx.getBean("jdbcTemplate");
jdbcTemplate.update("insert into kau_emp values(4,'forthmulga' )");
throw new RuntimeException();
}
并且在配置 XML 中有必要的配置。
我期待在抛出异常时回滚事务。但它没有回滚,并且记录被提交给 DB。
即使在互联网上进行了长时间搜索,我也无法理解为什么它没有被回滚。
后来我意识到,在 doTask() 代码中,我再次创建了上下文并将我们的 JdbcTemplate 实例从新的上下文中取出。这是问题的根本原因。
我更改了代码,使两个类都使用一些上下文。它奏效了!
public class SpringOraTest {
public static ApplicationContext aplctx;
public static void main(String[] args) {
aplctx= new FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml");
//Call to test Declarative Transaction with Annotation
TrxHandleAnnotated prxyobj=
((TrxHandleAnnotated)aplctx.getBean("dbCommandAnnotated"));
prxyobj.doTask();
}
@Transactional
public class TrxHandleAnnotated
public void doTask(){
JdbcTemplate jdbcTemplate=(JdbcTemplate)SpringOraTest.aplctx.getBean("jdbcTemplate");
jdbcTemplate.update("insert into kau_emp values(4,'forthmulga' )");
throw new RuntimeException();
}
这对我来说是一个教训,除非另有要求,否则整个应用程序应该只使用一个上下文对象。
这听起来太明显了 Spring 从业者,但像我这样的 Spring 新手会犯这种愚蠢的错误。于是想到分享。
在这种特殊情况下,最好将其声明为成员变量并使用 setter 注入,而不是手动创建 JdbcTemplate。