你的Spring事务为什么不会自动回滚?

Spring的事务传播行为有七种,当前我说的是默认的那种。我们知道Spring的声明式事务是基于AOP的,那么就是AOP玩的又是代理对象,那你是不是就知道了,这个事务的大概实现原理了。。。

首先我们要明确RuntimeException与Exception之间的关系与他们分别的含义:

1.在Java中异常的基类为Throwable,他有两个子类Exception与Errors,同时RuntimeException就是Exception的子类;

2.RuntimeException,即运行时异常,为非受检(UNCHECKED)异常;      

3.Exception的其他子类异常,为非运行时异常,为受检异常(CHECKED)异常;

Spring事务回滚机制是这样的:当所拦截的方法有指定异常抛出,事务才会自动进行回滚!

     ①被拦截方法-—— 注解式:方法或者方法所在类被@Transactional注解;

     ②异常—— 该方法的执行过程必须出现异常,这样事务管理器才能被触发,并对此做出处理;

    ③指定异常—— 默认配置下,事务只会对Error与RuntimeException及其子类这些UNChecked异常,做出回滚。一般的Exception这些Checked异常不会发生回滚(如果一般Exception想回滚要做出配置);

RuntimeException所包含的子类具体有哪些:

 下面给出一些受检CHECKED异常:

提醒:执行方法的时候出现了SQL执行的Exception事务还是发生了回滚,是因为Spring框架下,所有SQL异常都被org.springframework重写为RuntimeException!

还有一点当这个方法上加了@Transaction(此处是默认的传播行为)注解,当这个方法抛出RuntimeException之后被try catch之后声明式事务是不会感知的,当然也不会回滚,但是当在另一个也有事务的方法内调用了这个方法,形成嵌套事务,这个方法抛出了RuntimeException之后在上层方法内try catch的话,则上层方法的整个事务会被回滚。

 

 

已标记关键词 清除标记
我是学习spring新手, 碰到spring事务没有回滚的问题, 希望知道原因的指教,不胜感激: 我在mysql里建了一个测试的admin表(innoDB 类型), 只有id一个字段(整形)。 4条数据: id 1 2 3 4 配置文件: [code="java"] <bean name="/system/branch_modi" class="com.jandar.fdpweb.action.system.BranchOperationAction"> <property name="branchManage"> <ref bean="branchManage"/> </property> </bean> <bean id="branchManage" class="com.jandar.fdpweb.service.system.BranchManage"> <property name="branchTransaction"> <ref bean="branchTransaction"/> </property> </bean> <bean id="branchTransaction" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="myTransactonManager"/> </property> <property name="target"> <ref local="branchDao"/> </property> <property name="transactionAttributes"> <props> <prop key="deleteTest">PROPAGATION_REQUIRED, -Exception</prop> </props> </property> </bean> <bean id="branchDao" class="com.jandar.fdpweb.dao.jdbc.system.BranchDaoJdbcImpl"> <property name="jdbcTemplate"> <ref bean="jdbcTemplate" /> </property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref bean="c3p0DataSource" /> </property> </bean> <bean id="myTransactonManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="c3p0DataSource"/> </property> </bean> <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass"> <value>com.mysql.jdbc.Driver</value> </property> <property name="jdbcUrl"> <value>jdbc:mysql://localhost:3306/cjr_test?characterEncoding=utf8</value> </property> <property name="user"> <value>root</value> </property> <property name="password"> <value>123456</value> </property> <property name="initialPoolSize"><value>10</value></property> <property name="minPoolSize"><value>5</value></property> <property name="maxPoolSize"><value>20</value></property> <property name="acquireIncrement"><value>5</value></property> <property name="maxIdleTime"><value>60</value></property> <property name="maxStatements"><value>0</value></property> </bean> [/code] Struts Action 类: [code="java"] public class BranchOperationAction extends DispatchAction { private BranchManage branchManage; public BranchManage getBranchManage() { return branchManage; } public void setBranchManage(BranchManage branchManage) { this.branchManage = branchManage; } public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { ActionForward forward = new ActionForward(); DynaActionForm modifyForm = (DynaActionForm) form; String branchId = modifyForm.getString("branch_tj").trim(); branchManage.deleteTest(branchId); forward = mapping.findForward("success"); return (forward); } } [/code] Server 类: [code="java"] public class BranchManage { private BranchDao branchTransaction; public BranchDao getBranchTransaction() { return branchTransaction; } public void setBranchTransaction(BranchDao branchTransaction) { this.branchTransaction = branchTransaction; } public void deleteTest(String branchId) { branchTransaction.deleteBranch(branchId); } } [/code] DAO 类: [code="java"] public interface BranchDao { public void deleteBranch(final String branchId); } public class BranchDaoJdbcImpl implements BranchDao { private JdbcTemplate jdbcTemplate; public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void deleteBranch(final String branchId) { String sqlDelete1 = "delete from admin where id = 1"; // 先删除一条记录 int[] arr = {1, 2, 3, 4}; jdbcTemplate.update(sqlDelete1); //我调试时, 程序运行这行后, 数据库居然删了一行, 事务这时应该没提交,不会删数据库才对啊, 是这样吗? //数组下标越界,想让程序抛出Runtime Exception String sqlDelete2 = "delete from admin where id = " + arr[5]; jdbcTemplate.update(sqlDelete2); // 删除第二条报错,事务没有回滚 } } [/code]
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页