<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">近来在项目中,有关功能需要进行事务处理,因为以前很少用事务所以也没注意这个事,因此走了些弯路!今天特此记录一下.希望能给正在迷茫的你带来一丝灵光!</span>
要达到的目的(使用注解方式):
在service类中写一个业务方法,里面有删除+保存两个操作,如果保存失败,删除需要回滚
出现的问题描述:
以下是service层的业务代码(非完整,样例)
</pre><pre name="code" class="html"> @Service
public class RoleService {
@Resource
protected WebRoleMenuMapper webRoleMenuMapper;
public void addRoleMenu(RoleMenuForm formBean) throws MyDBException{
XXX
.
.
.
webRoleMenuMapper.deleteByRoleId(roleId);
webRoleMenuMapper.insert_batch(listWebRoleMenu);
} catch (Exception e) {
throw new MyDBException("数据库操作异常,需要回滚操作");
}
以下是applicationContext.xml事务的相关配置
<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<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="*" propagation="REQUIRED" read-only="false" rollback-for="MyDBException" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="interceptorPointCuts"
expression="execution(* cn.iwojia.web.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" />
</aop:config>
理论上一切OK了.(后来一种想法被证实)
实际操作中,是回滚不了..然后各种尝试,改抛异常为runtime异常,数据库操作异常,等等..后来又拿出以前的项目来比较,改配置..让老友帮自己成配置等等...都没用,很着急很迷茫.后来无意问发现相同问题贴子中有人评论讲可能是加载顺序及注入事务覆盖问题.然后一番搜索看到这么一项!大致是说spring能加载数据源后事务,而mvc只能当普通bean加载!
那么现在问题来了.在Mvc.XML中配置<context:component-scan base-package="cn.iwojia" />(粗略扫描),这里面包括service,contorller,那么做为普通Bean加载,也就是不使用事务的时候没有任何问题的..
通用解决方法:
1.在spring文件里面加载除controller以外的注解
2.在mvc文件里面加载contorller,但是不要加载service注解
贴上配置
spring配置:
<context:component-scan base-package="cn.iwojia">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
mvc配置:
<context:component-scan base-package="cn.iwojia">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Service" />
</context:component-scan>
好了.截止这里.你的事务已经生效了.
注意:controller,service注解在功能是一样的.为了区分不同层,一定要区分用
思考: 你不觉得这样配置是补救方式么?有点不和谐
既然明白了原理,那我认为只要在spring.xml中加载service层的类,mvc.xml加载controll类..那就没问题了啊
怎么实现呢:那就是要(精细扫描).
就是要把包名写到具体的业务类的包名上..看配置
更改后spring.xml中的配置
<context:component-scan base-package="cn.iwojia.web.service" />
更改后mvc.xml中的配置
<context:component-scan base-package="cn.iwojia.web.action" />
<context:component-scan base-package="cn.iwojia.web.base.action" />
OK!测试事务正常回滚
总结:
1.因为省事搞个全包扫描,结果一个问题,把省的时间都返回来了,还得加倍
2.框架多数跟配置有关,要习惯从官方文档或评论大神那里找答案
留个问题吧:
如果serivce层不用注解方式,配置又要怎么写?有空再研究这个吧
参考:http://blog.sina.com.cn/s/blog_6c969b4a0102vgcz.html
欢迎大家就技术方面跟贴探讨!