在 spring 引导应用程序中将多个调用包装在一个事务中?
wrapping multiple calls in a transaction in spring boot application?
我正在使用 jdbctemplate 在我的 spring 应用程序中对数据库执行查询。
这里是用@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上的事务会回滚吗?我该如何测试?
此外,使用布尔值作为 return 值是否是指示事务状态的良好做法?
如果3失败,1和2会回滚。这是事务(工作单元)的核心点。
基于@Zergleb 的回答的重要更正:仅当您抛出异常时。在您的代码中,您正在处理异常,因此 1 和 2 将持续存在,因为事务没有 "see" 异常,它不知道有什么问题。
为了测试,在 sql3
中放入一些无效的 sql,看看会发生什么。
我通常不会 return 布尔值来表示成功。 Success 是该方法的成功完成,如果您的场景指示这样,您应该让异常冒泡或将异常包装在更合适的东西中并抛出它。
例如:
@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);
}
}
如果1和2成功,3失败,1和2上的事务会回滚吗?
如果第三次操作失败,将回滚第一次和第二次操作。但如果它们是同一事务或事务上下文的一部分。
例如,如果您将事务管理器定义为 DataSourceTransactionManager,它将回滚同一连接的 JDBC 操作。在您的情况下,您在同一个方法中执行了所有三个操作并且使用了相同的 jdbcTemplate,因此它将回滚您的其他两个事务。
如果使 sql 指令失败,您可以对此进行测试,例如:
- 插入正确
- 插入正确
- INSERT 但您可以尝试在数字列中插入字符串,或在非空列中插入空值。
你可以在这里看到更多
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
关于返回boolean我觉得还是抛异常比较好,会自动回滚事务
不!如果您捕获异常,您的 sql 将不会回滚!!!!
这不会触发回滚。您需要删除 try-catch。但是,是的,如果抛出运行时异常,这些将按预期回滚。请参考以下文档。
@Transactional settings
您会看到下面的几行,回滚是由任何 RuntimeException 触发的。因此,如果您捕获到异常,它不会触发回滚,它只会在您 return false 时结束事务。进一步注意,如果你抛出一个已检查的异常,它不会回滚,所以不要试图通过抛出一个异常来解决这个问题,无论你打算用那个布尔值 return 值做什么。
我自己还没有尝试过,但是如果你在@Transactional 上设置 rollbackFor 属性 或者可能只是在这个方法的外部捕获 RuntimeException,你似乎可以回滚检查的异常?或者抛出你自己的运行时异常?我把它留给你。
如上所述,这也适用于存储库,您可以在此处查看示例
Spring Data(Repositories) transactions
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
我正在使用 jdbctemplate 在我的 spring 应用程序中对数据库执行查询。
这里是用@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上的事务会回滚吗?我该如何测试?
此外,使用布尔值作为 return 值是否是指示事务状态的良好做法?
如果3失败,1和2会回滚。这是事务(工作单元)的核心点。
基于@Zergleb 的回答的重要更正:仅当您抛出异常时。在您的代码中,您正在处理异常,因此 1 和 2 将持续存在,因为事务没有 "see" 异常,它不知道有什么问题。
为了测试,在 sql3
中放入一些无效的 sql,看看会发生什么。
我通常不会 return 布尔值来表示成功。 Success 是该方法的成功完成,如果您的场景指示这样,您应该让异常冒泡或将异常包装在更合适的东西中并抛出它。
例如:
@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);
}
}
如果1和2成功,3失败,1和2上的事务会回滚吗?
如果第三次操作失败,将回滚第一次和第二次操作。但如果它们是同一事务或事务上下文的一部分。
例如,如果您将事务管理器定义为 DataSourceTransactionManager,它将回滚同一连接的 JDBC 操作。在您的情况下,您在同一个方法中执行了所有三个操作并且使用了相同的 jdbcTemplate,因此它将回滚您的其他两个事务。
如果使 sql 指令失败,您可以对此进行测试,例如:
- 插入正确
- 插入正确
- INSERT 但您可以尝试在数字列中插入字符串,或在非空列中插入空值。
你可以在这里看到更多 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
关于返回boolean我觉得还是抛异常比较好,会自动回滚事务
不!如果您捕获异常,您的 sql 将不会回滚!!!!
这不会触发回滚。您需要删除 try-catch。但是,是的,如果抛出运行时异常,这些将按预期回滚。请参考以下文档。
@Transactional settings
您会看到下面的几行,回滚是由任何 RuntimeException 触发的。因此,如果您捕获到异常,它不会触发回滚,它只会在您 return false 时结束事务。进一步注意,如果你抛出一个已检查的异常,它不会回滚,所以不要试图通过抛出一个异常来解决这个问题,无论你打算用那个布尔值 return 值做什么。
我自己还没有尝试过,但是如果你在@Transactional 上设置 rollbackFor 属性 或者可能只是在这个方法的外部捕获 RuntimeException,你似乎可以回滚检查的异常?或者抛出你自己的运行时异常?我把它留给你。
如上所述,这也适用于存储库,您可以在此处查看示例
Spring Data(Repositories) transactions
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions