Spring事务管理——回滚(rollback-for)控制
来源:互联网 发布:css布局 知乎 编辑:程序博客网 时间:2024/05/18 03:37
探讨Spring事务控制中,异常触发事务回滚原理。文章进行了6种情况下的Spring事务是否回滚。
以下代码都是基于Spring与Mybatis整合,使用Spring声明式事务配置事务方法。
1.不捕获异常(一般处理方式)
代码,其中contentMappger.updateWithErrTest(31L);
是SQL语句错误,用来测试回滚。
/** * 删除多条记录 */ @Override public ShopResult deleteContentGroup(String[] ids) { if (null == ids || ids.length == 0) { return ShopResult.error(); } for (String idStr : ids) { Long id = new Long(idStr); contentMappger.deleteByPrimaryKey(id); } contentMappger.updateWithErrTest(31L); //错误代码,SQL语句错误。用来测试事务,看是否回滚 return ShopResult.ok(); }
运行结果:报错,事务发生了回滚,即由于错误代码,前面的for循环删除记录事务被回滚了。
### SQL: delete form tb_content where kid = ?### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tb_content where kid = 31' at line 1; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tb_content where kid = 31' at line 1] with root causecom.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tb_content where kid = 31' at line 1 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.jdbc.Util.handleNewInstance(Util.java:406) at com.mysql.jdbc.Util.getInstance(Util.java:381) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1030) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3536) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3468) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1957) .................. at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53) at com.sun.proxy.$Proxy35.updateWithErrTest(Unknown Source) at com.shop.manager.service.impl.ContentServiceImpl.deleteContentGroup(ContentServiceImpl.java:94) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) .......
2. 捕获异常,但不处理,不抛出
代码
/** * 删除多条记录 */ @Override public ShopResult deleteContentGroup(String[] ids) { if (null == ids || ids.length == 0) { return ShopResult.error(); } for (String idStr : ids) { Long id = new Long(idStr); contentMappger.deleteByPrimaryKey(id); } try { contentMappger.updateWithErrTest(31L); //错误代码,SQL语句错误。用来测试事务,看是否回滚 } catch (Exception e) { //捕获异常,但不处理 System.out.println("-----nothing to do-------"); } return ShopResult.ok(); }
运行结果:事务提交,未回滚。
### The error occurred while setting parameters### SQL: delete form tb_content where kid = ?### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tb_content where kid = 31' at line 1]-----nothing to do-------2017-06-18 14:27:59,493 [http-bio-8080-exec-4] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Transaction synchronization committing SqlSession //(事务提交)[org.apache.ibatis.session.defaults.DefaultSqlSession@616a85a9]
3. 捕获异常,并抛出RuntimeException异常
Spring碰到Unchecked Exceptions都会回滚,不仅是RuntimeException,也包括Error。
代码
/** * 删除多条记录 */ @Override public ShopResult deleteContentGroup(String[] ids) { if (null == ids || ids.length == 0) { return ShopResult.error(); } for (String idStr : ids) { Long id = new Long(idStr); contentMappger.deleteByPrimaryKey(id); } try { contentMappger.updateWithErrTest(31L); //错误代码,SQL语句错误。用来测试事务,看是否回滚 } catch (Exception e) { System.out.println("----throw Exception-----"); throw new RuntimeException(); } return ShopResult.ok(); }
运行结果:如预期的一样,抛出RuntimeException,事务发生回滚。
### SQL: delete form tb_content where kid = ?### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tb_content where kid = 31' at line 1]----throw Exception-----2017-06-18 14:21:27,928 [http-bio-8080-exec-1] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3ef56e3a]...............2017-06-18 14:21:27,941 [http-bio-8080-exec-1] [org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver]-[DEBUG] Resolving exception from handler [public com.shop.common.pojo.ShopResult com.shop.manager.controller.ContentController.deleteContentGroup(java.lang.String)]: java.lang.RuntimeException2017-06-18 14:21:27,941 [http-bio-8080-exec-1] [org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver]-[DEBUG] Resolving exception from handler [public com.shop.common.pojo.ShopResult com.shop.manager.controller.ContentController.deleteContentGroup(java.lang.String)]: java.lang.RuntimeException2017-06-18 14:21:27,942 [http-bio-8080-exec-1] [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver]-[DEBUG] Resolving exception from handler [public com.shop.common.pojo.ShopResult com.shop.manager.controller.ContentController.deleteContentGroup(java.lang.String)]: java.lang.RuntimeException2017-06-18 14:21:27,942 [http-bio-8080-exec-1] [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Could not complete requestjava.lang.RuntimeException at com.shop.manager.service.impl.ContentServiceImpl.deleteContentGroup(ContentServiceImpl.java:98) //异常 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
4.捕获异常,并继续抛出原捕获的异常
代码:
/** * 删除多条记录 */ @Override public ShopResult deleteContentGroup(String[] ids) { if (null == ids || ids.length == 0) { return ShopResult.error(); } for (String idStr : ids) { Long id = new Long(idStr); contentMappger.deleteByPrimaryKey(id); } try { contentMappger.updateWithErrTest(31L); //错误代码,SQL语句错误。用来测试事务,看是否回滚 } catch (Exception e) { //捕获异常,继续抛出 System.out.println("-----throw Exception-------"); throw e; } return ShopResult.ok(); }
运行结果:抛出异常,事务发生回滚
### The error occurred while setting parameters### SQL: delete form tb_content where kid = ?### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tb_content where kid = 31' at line 1]-----throw Exception-------2017-06-18 14:36:25,308 [http-bio-8080-exec-9] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@45fe0f70]2017-06-18 14:36:25,308 [http-bio-8080-exec-9] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Transaction synchronization closing SqlSession //事务回滚[org.apache.ibatis.session.defaults.DefaultSqlSession@45fe0f70]
5. 捕获异常,并抛出新new的异常(或自定义Exception异常) new Exception
代码:
/** * 删除多条记录 * @throws Exception */ @Override public ShopResult deleteContentGroup(String[] ids) throws Exception { if (null == ids || ids.length == 0) { return ShopResult.error(); } for (String idStr : ids) { Long id = new Long(idStr); contentMappger.deleteByPrimaryKey(id); } try { contentMappger.updateWithErrTest(31L); //错误代码,SQL语句错误。用来测试事务,看是否回滚 } catch (Exception e) { //捕获异常,抛出新异常 System.out.println("-----throw new Exception(e)-------"); throw new Exception(e); } return ShopResult.ok(); }
运行结果:事务提交,未回滚。(Spring的默认回滚异常类型不包括Exception)
### The error occurred while setting parameters### SQL: delete form tb_content where kid = ?### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tb_content where kid = 31' at line 1]-----throw new Exception(e) -------2017-06-18 14:43:16,098 [http-bio-8080-exec-10] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Transaction synchronization committing SqlSession //事务提交[org.apache.ibatis.session.defaults.DefaultSqlSession@32c4821]2017-06-18 14:43:16,098 [http-bio-8080-exec-10] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32c4821]
6. 在事务配置中没有设置rollback-for异常类型为Exception
<!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 事务行为控制 --> <tx:attributes> <tx:method name="save" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="create*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="select*" propagation="SUPPORTS" read-only="true" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> <!-- 配置切面 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.shop.manager.service.*.*(..))" /> </aop:config>
/** * 删除多条记录 * @throws Exception */ @Override public ShopResult deleteContentGroup(String[] ids) throws Exception { if (null == ids || ids.length == 0) { return ShopResult.error(); } for (String idStr : ids) { Long id = new Long(idStr); contentMappger.deleteByPrimaryKey(id); } try { contentMappger.updateWithErrTest(31L); //错误代码,SQL语句错误。用来测试事务,看是否回滚 } catch (Exception e) { //捕获异常,继续抛出 System.out.println("-----throw new Exception-------"); throw new Exception("---自定义Exception,事务中已配置rollback-for---"); } return ShopResult.ok(); }
运行结果:如预期一样发生回滚
### The error may involve com.shop.manager.mapper.TbContentMapper.updateWithErrTest-Inline### The error occurred while setting parameters### SQL: delete form tb_content where kid = ?### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tb_content where kid = 31' at line 1]-----throw new Exception-------2017-06-18 15:07:02,273 [http-bio-8080-exec-8] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f177061]2017-06-18 15:07:02,273 [http-bio-8080-exec-8] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f177061]
总结:
- Spring事务管理是根据异常来进行回滚操作;
- Spring与Mybatis整合时,虽然在Service方法中并没有check异常,但是如果数据库有异常发生,默认会进行事务回滚。
- Spring 如果不添加rollbackFor等属性,Spring碰到Unchecked Exceptions都会回滚,不仅是RuntimeException,也包括Error。
- 如果在事务方法中捕获异常并进行处理,一定要继续抛出异常并在Spring事务管理中进行rollbak-for配置。
阅读全文
0 0
- Spring事务管理——回滚(rollback-for)控制
- Spring事务管理——回滚(rollback-for)控制
- Spring transaction事务之roll back回滚: rollback-for
- Spring transaction事务之roll back回滚: rollback-for
- Spring transaction事务之roll back回滚: rollback-for
- Spring transaction事务之roll back回滚: rollback-for
- spring 事务管理——回滚之service层(事务控制层)代码互调
- spring 事务管理——回滚之service层(事务控制层)代码互调
- Spring事务管理-回滚
- Connection. rollback方法—事务回滚
- spring事务管理 junit回滚
- spring事务管理 junit回滚
- spring事务管理 事务回滚
- spring事务管理 junit回滚
- 回滚 rollback
- git 回滚rollback
- spring 声明式事务管理,回滚不起作用
- Spring自动回滚的事务管理配置
- 给初级java程序员推荐几个学习网站--雷锋
- 删除文件时提示“您需要计算机管理员提供的权限才能完成此操作”
- IDA* 算法(Iterative deepening A*)
- Scala基础—异常、Lazy使用示例
- (document).height()与$(window).height()
- Spring事务管理——回滚(rollback-for)控制
- 20. 电话号码
- android studio实现打电话
- GCC笔记(警告.优化以及调试选项)
- 23种设计模式--结构型模式(适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式)
- 父进程退出后如何通知子进程退出
- ORACLE Unit05 视图、序列、索引 、 约束
- Oracle那些事(11)-SQL单表查询
- 21. 吃货续