更多spring事务问题请访问链接:Spring事务回滚疑难详解
1,我们要明确,Spring如何设置让事务自动提交和回滚?
①如何自动提交?
理论上,可以通过对DataSource如下设置,让事务自动提交
-
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="defaultAutoCommit" value="true">property>
- bean>
实际上,这个设置对于大多数数据源是没有必要的,例如"org.apache.commons.dbcp.BasicDataSource"
(我们可以通过反编译插件或者反编译工具浏览该jar包),我们发现
- public BasicDataSource() {
- this.defaultAutoCommit = true;
- this.defaultReadOnly = null;
- /*此类通过无参的构造方法实例化:new BasicDataSource()*/
上述表明:该数据源通过构造方法,初始化成员变量,defaultAutoCommit默认为true。
②如何自动回滚?
详情访问链接:Spring事务为什么没有回滚?Spring事务怎样才会回滚?事务回滚的条件
2,想要Spring对事务实现自动管理,首先我们要为数据源配置事务管理器
SSH中配置如下:
-
-
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="${jdbc_driverClassName}">property>
- bean>
-
- <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- bean>
-
- <bean id="transactionManager"
- class="org.springframework.orm.hibernate4.HibernateTransactionManager">
- <property name="sessionFactory" ref="sessionFactory" />
- bean>
SSM中配置如下:
-
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="${jdbc_driverClassName}">property>
- bean>
-
-
- <bean name="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- bean>
总结:Mybatils与hibernate在事务管理配置上有差别 —— Mybatils通常使用Spring默认的数据源事务管理器只要求相同数据源,不做其他配置;Hibernate使用专门的Spring事务管理器需要引用具备相同数据源的SessionFactory。
3,Spring的事务管理方式有哪几种?如何配置并使用?(事务管理器创建完成,以它为基础配置事务标识——用来创建并管理事务)
包含两种: 编程式事务管理、声明式事务管理
(一)其中编程式管理带来代码冗余,违背Spring简洁特性,基本上很少使用,例如:
- int a=consumpDao.insert(s);//插入消费明细
- int b=customerDao.insert(customer);//此处实际应该update(customer),不然会出现重复主键的异常
- int d=0;
- if(a*b*d==1){
- json.put("result",0);
- json.put("msg", "购买成功");
- json.put("data", "");
- }else{
- json.put("result",-1);
- json.put("msg", "购买失败");
- json.put("data", "");
- TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
- }
其中使用程序TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 在没有异常抛出的情况下实现
事务的手动回滚,如有疑问请访问链接:Spring事务为什么没有回滚?Spring事务怎样才会回滚?事务回滚的条件
注意:尽管可以采用编程式方法回滚事务,但“回滚”只是事务的生命周期之一,所以要么编程实现事务的全部必要周期,要么仍要
配置事务切点,即,将事务管理的其他周期交由Spring的标识!
(二)其中声明式管理符合Spring的特性,被广泛使用 —— 注解易于配置,配置易于编程 ,它的实现具有两种常用方式:
①一种是基于tx和aop切面拦截的xml配置文件:
- <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
-
- <tx:attributes >
- <tx:method name="insert*" propagation="REQUIRED" />
- <tx:method name="get*" propagation="REQUIRED" read-only="true" />
- tx:attributes>
- tx:advice>
- <aop:config expose-proxy="true">
- <aop:pointcut id="transactionPointcut" expression="execution(* com.local.*.*.*(..))" />
- <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
- aop:config>
需要注意一下expression中*通配符的含义:
当然,大多数时候我们都是在service层,实现事务管理的,即配置如下:
- <aop:config expose-proxy="true">
- <aop:pointcut id="transactionPointcut" expression="execution(* com.local.service.*.*(..))" />
- <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
- aop:config>
只要在expression描述的范围下,方法名符合配置格式,事务的 ①开启 ②提交 ③回滚 ④关闭 ⑤清空就会依据具体配置交由Spring管理:
- @RequestMapping("consump")
- public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{
- JSONObject json =new JSONObject();
②另一种就是基于@Transactional注解:
-
- <tx:annotation-driven transaction-manager="transactionManager" />
@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
- @Transactional
- @RequestMapping("consump")
- public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{
- JSONObject json =new JSONObject();