我正在使用jdbctemplate在我的spring应用程序中对db执行查询。
以下是使用@Transactional
注释的方法@Transactional
public boolean doSomething(){
try {
jdbcTemplate.update(sql1); //1
jdbcTemplate.update(sql2); //2
jdbcTemplate.update(sql3); //3
return true;
} catch (Exception ex){
return false;
}
}
我的问题是,如果1和2成功而3失败,1和2上的交易是否会回滚?我该怎么测试呢?
另外,布尔值作为返回值是指示交易状态的好习惯吗?
答案 0 :(得分:5)
否!如果你捕获异常,你的sql将不会回滚!!!!
这不会触发回滚。你需要删除try-catch。但是,如果抛出运行时异常,这些将按预期回滚。请参考以下文档。
@Transactional settings
您将看到几行内容,任何RuntimeException都会触发回滚。因此,如果您捕获异常,它将不会触发回滚,它将在您返回false时简单地结束事务。另外请注意,如果你抛出一个已检查的异常,它将不会回滚,所以不要试图通过抛出异常来解决这个问题,以便做你要对该布尔返回值做的任何事情。
我自己没有试过这个但是如果你在@Transactional上设置rollbackFor属性或者在这个方法的外部捕获RuntimeException,你似乎可以回滚已检查的异常?或抛出自己的运行时异常?我把它留给你。
如上所述,这也适用于您可以在此处查看示例的存储库
Spring Data(存储库)事务
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
答案 1 :(得分:1)
如果3失败,则1和2将回滚。这是交易的核心要点(工作单位) 基于@ Zergleb答案的重要更正:仅在您抛出异常时才会发生。在你的代码中,你正在咀嚼异常,因此1和2将持续存在,因为事务没有“看到”它不知道出现任何错误的异常。
要测试,在sql3
中放入一些无效的sql,看看会发生什么。
我通常不会返回一个布尔值来表示成功。成功是方法的成功完成,你应该让异常冒泡或者将异常包装成更合适的东西,如果你的场景表明这样的话,就抛出异常。
例如:
@Transactional
public void doSomething(){
try {
jdbcTemplate.update(sql1); //1
jdbcTemplate.update(sql2); //2
jdbcTemplate.update(sql3); //3
} catch (Exception ex){
throw new MyCustomPersistenceException("Could not doSomething", e);
}
}
答案 2 :(得分:1)
如果1和2成功且3失败,1和2上的交易是否会回滚?
如果第三个操作失败,则第一个和第二个操作将回滚。但如果它们是同一交易或交易环境的一部分。
例如,如果将事务管理器定义为DataSourceTransactionManager,它将回滚同一连接的JDBC操作。在您的情况下,您在同一方法中拥有所有三个操作并使用相同的jdbcTemplate,因此它将回滚您的其他两个事务。
如果使sql指令失败,您可以测试它,例如:
你可以在这里看到更多 http://www.journaldev.com/2603/spring-transaction-management-jdbc-example
http://docs.spring.io/autorepo/docs/spring/4.2.x/spring-framework-reference/html/transaction.html
关于返回布尔值我认为抛出异常会更好,它会自动回滚事务。