网上关于这里事务功能实现的帖子有很多了。
首先,我们了解下事务管理有几种常用方式。
1.声明式事务管理—AOP实现
2.注解式事务管理—@Transactional
3.编程式事务管理—写代码
但是大多数情况下我们不能很顺利的实现事务功能。
一般有两个坑:
1.spring.xml扫描范围和spring-mvc.xml扫码范围重复了。
这个问题的解决核心思想就是
经过测试,其实问题主要在于SpringMVC的配置文件扫包范围,Spring的配置文件就算也扫了@Controller注解,但是在 SpringMVC会重新扫描一次,事务管理的Service只要没被重复扫描就不会出现事务失效问题。
2.开启注解事务功能。
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
3.我们在添加@Transactional注解时候,一定要引用下面这个包的Transactional
import org.springframework.transaction.annotation.Transactional;
一般情况,注意到这两点,基本能实现在service层的事务管理。
但是,有一种特殊情况,可能存在这样的需求,把事务做到controller层。
理论依据:
实例讲解:
大致内容如下描述:
一般的配置方法是让Spring管理除了Controller注解以外注解,而让SpringMVC单纯管理Controller注解。
也就是说Spring有一个配置文件,里面配置成扫描非Controller的bean,SpringMVC有一个配置文件,里面只扫描Controller。
这样就形成了两个上下文,即Spring的上下文和SpringMVC的上下文,他们分别管理着不同的俩堆bean。
这个时候你在Spring的配置文件里加了一句tx:annoation-driven,其实是告诉Spring,你管理的这些bean里面有可能会出现需要事务支持的。
然后在Spring管理范围的某个bean上加了个注解@transactional,其实是用来帮助Spring识别这个bean是需要事务管理的。
同样你在Spring的配置文件里加了tx:annoation-driven,SpringMVC是不关心的,他只关心你给他配置了什么以及他管理的bean上有什么注解
第一种方式:编程式事务
这种方式试用于:
1.数据库为mysql数据。
2.sqlserver数据库失败。
另外我觉得这种方式失败可能是因为编程事务管理,要手动关闭回滚,但是为什么mysql不用手动关闭了?
第二种方式:注解事务管理。
1.@Transactional注解的包不要引用错误。
2.数据库连接池用druid连接池,不能用spring自带的。
3.注解事务做到controller层的关键点
在DispatcherServlet对应的spring xml 文件中加上这句话。
<tx:annotation-driven transaction-manager="transactionManager" />
另外数据库连接池不能用这个,否则,sqlserver事务失效
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">