环境:mybatis3.3,spring3.2,druid
我是将事物交给springAOP进行管理,采用的xml方式配置,同时开启支持注解式事物驱动。
<!-- 下面是配置声明式事务管理的,个人感觉比用注解管理事务要简单方便 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="OracledataSource"></property>
</bean>
<!-- 定义事务传播属性 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="insert*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="update*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="remove*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="delete*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<!-- proxy-target-class="true" 解决spring自动注解不能自动动态转换接口类成实现类的问题;
默认状态下,proxy-target-class属性的值为false,
那么被代理类是基于javaSE(JDK)的动态代理(一般被代理类会实现接口);
如果显式的设置了proxy-target-class属性的值为true,
那么被代理类就将基于cglib动态代理(spring框架中的代理)-->
<aop:config proxy-target-class="true">
<!-- 管理事务操作 说明在这个包中的这些类中的这些方法应用前面 txAdvice 的配置事务传播属性-->
<aop:advisor pointcut="execution(* com.erp.*.service..*.*(..))"
advice-ref="txAdvice" />
</aop:config>
<!-- 把扫描Service的配置放在配置事务的后面而不是SpringMVC的配置中主要是避免配置文件的加载顺序
先加载SpringMVC后加载这儿这个配置文件导致 事务不起作用 -->
<!-- 配置spring扫描所有Service和Repository组件自动装配 -->
<!--自动扫描含有@Service将其注入为bean -->
<context:component-scan base-package="com.erp.*.service" />
<!--自动扫描含有@Repository将其注入为bean -->
<context:component-scan base-package="com.erp.*.dao" />
配置方式很多,具体大家可以去网上查找,此处就不赘述了,这里之说下可能造成事物失效的原因:
前提是你的事物配置不会出现基本的错误,如excution表达式的错误,导致不能正确的注入事物,以及advice中指定注册的事物管理bean等
一:想必大家都用了springMVC,并且使用了其扫描器组件,对项目中加入servcie /ctroller注解的bean进行注册交给srping容器管理,在springMVC配置文件中我们只扫描ctroller对所有的service进行过滤掉,因为按照spring配置文件的加载顺序来讲,先加载springmvc配置文件,再加载spring配置文件,我们的事物一般都在srping配置文件中进行配置,如果此时在加载srpingMVC配置文件的时候,把servlce也给注册了,但是此时事物还没加载,也就导致后面的事物无法成功注入到service中。所以把对service的扫描放在spring配置文件中或是其他配置文件中。
二:如果以上步骤都没问题,事物还是失效,查看事物配置中的excution表达式路径是否正确,查看rollback-for指定的异常类是否有,通过Log4j ,debug模式将事物日志打印出来,在方法中手动new一个异常抛出(throw new RuntimeException())看是否事物回滚了,注意异常抛出要在service层
三:如果你用了mysql数据库,查看数据库存储引擎,MyISAM是不支持事物的,需要改成InnoDB
四:如果Service中有方法间的调用当且使用cglib动态增强aop时,注意每个方法都声明了事务。