在维护一个之前搭建的框架,SpringMVC框架,看着所有的配置都正常,而且也一直在使用,可是当我编写好代码时突然想到,我的逻辑里面要插入好几次SQL,这里面的事物是否管用呢?
于是我测试了一下,竟然是不起作用。改配置,加注解,各种操作都试了,aop:config和tx:advice配置看着都对,可事物就是不起作用。
偶然间看到网上有人说context:component-scan配置不当会引起事物不起作用,看了一下,果然,该框架扫描直接在SringMVC配置文件中写了一个根路径。
于是修改SpringMVC只扫描Controller包
<context:component-scan base-package="com.csq.action"/>
Spring配置扫描所有包但是拍出Controller包
<context:component-scan base-package="com.jlc">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
其他不动,测试事物已经生效。
如果是那种分模块的包,比如A模块下面分了action,service,dao,然后B、C。。。模块都是这样,怎么扫描呢?
<context:component-scan>提供两个子标签:<context:include-filter>和<context:exclude-filter>各代表引入和排除的过滤。
<!-- 排除controller注解支持 -->
<context:component-scan base-package="com.test">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 开启controller注解支持 -->
<context:component-scan base-package="com.b505.web">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
根据这次问题,总结了可能出现此类问题的原因,仅供参考:
(1)事务方法内部捕捉了异常,没有抛出新的异常,导致事务操作不会进行回滚。
(2)在类内部调用调用类内部@Transactional标注的方法。这种情况下也会导致事务不开启。
(3)Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用。
(4)数据库本身对应的库、表所设置的引擎是什么。MyIsam不支持事务,如果需要,则必须改为InnnoDB。
(5)@Transactional所注解的方法所在的类,是否已经被注解@Service或@Component等。
(6)注解为事务范围的方法中,事务的回滚仅仅对于unchecked的异常有效。对于checked异常无效。也就是说事务回滚仅仅发生在出现RuntimeException或Error的时候。如果希望一般的异常也能触发事务回滚,需要在注解了@Transactional的方法上,将@Transactional回滚参数设为:
@Transactional(rollbackFor=Exception.class)
END