##########################万能分割线#########################
最近在使用springmvc结合mysql开发时候,遇到一个问题,基于注解的事务配置在程序运行中事务无效,即不进行事务回滚。下面说说如何解决该问题......
(现在常规MySQL都是使用INNODB存储引擎,即都是支持事务的)
############################################################
<1>代码块:[service层的staffService.java]
@Transactional(rollbackFor = Exception.class)
public Map<String,Object> deleteStaffByIds(Long currentStaffId,List<Long> staffsidList,List<Long> merchantsId,Long cityId) throws Exception {
......
try {
//删除人员商户表信息
staffDao.deleteStaffMerchant(staffsidList,merchantsId);
//删除人员角色表信息
staffDao.deleteStaffRole(staffsidList);
//删除人员城市表信息
staffDao.deleteStaffCity(staffsidList,cityId);
} catch (Exception e) {
log.error("关联删除人员信息失败,失败信息: "+e.getMessage());
logService.insertWebLog(currentStaffId, sOperateClass, sMethodName, "失败",retMesg);
throw e;
}
....
}
上述代码块使用了基于@Transaction注解事务进行回滚设置,测试设置:使得在删除deleteStaffMerchant、deleteStaffRole方法成功后,设置最后的deleteStaffCity方法在执行操作数据库时候跑出异常,正常情况即事务回滚的情况下,前面两个方法删除的记录会恢复,进行事务回滚。但是在测试时候发现并没有执行事务回滚。
之后,检查了配置文件:
<2>applicationContext.xml配置:
<!-- 设置需要进行Spring注解扫描的类包 -->
<context:component-scan base-package="com.xianSky" />
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dbDataSource"></bean>
<!-- 注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
数据库连接池与事务管理器,注解扫描都没有问题....之后又查看了springMVC配置文件
<3>springMVC-servlet.xml配置:
<!-- 当我们需要controller返回一个map的json对象时,可以设定<mvc:annotation-driven /> -->
<mvc:annotation-driven />
<!-- 设置需要进行Spring注解扫描的类包 -->
<context:component-scan base-package="com.xianSky" />
配置了简单的注解驱动与注解扫描包....似乎也是没有问题
之后结合该篇文章所说:http://blog.csdn.net/z69183787/article/details/37819831
更深入的了解到了,当web容器启动时候,会初始化两个容器,在容器装配bean时候会根据配置的扫描表进行装配。问题就在这了,对项目的三层所有类扫描会进行两次。
第一次是applicationContext配置对应的容器,第二次是springMVC配置文件对应的子容器。
注意到上述的配置文件:<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 该段配置事务注解是放在applicationContext中,即只是对父容器中扫描的类具有注解事务功能,在springMVC中的配置并没有配置该内容,所以造成了:
在第一次扫描装配bean时候,bean是具有事务功能的。但是在springmvc二次扫描情况下,会覆盖父类容器中扫描的bean功能,因为没有配置注解驱动,所以就在service代码中不支持事务回滚,尽管加上了事务注解。所以有两种解决方法:
A:在springMVC子容器扫描包的时候,不扫描使用到事务的service层的所有类。在springMVC-servlet.xml中配置:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
</tx:annotation-driven>
这样就不会将具有事务功能的service层的类进行扫描和功能覆盖。
B:将父类applicationContext.xml配置文件中的事务注解驱动配置代码:<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
从父类配置文件中剪切到子容器springMVC-servlet.xml中,这样,在子容器进行bean装配扫描时候,就具备了事务功能。
<!-- 设置需要进行Spring注解扫描的类包 -->
<context:component-scan base-package="com.cybbj" />
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
至此...............done.