【问题解决】SSM-@Transactional注解事务无效探讨

简介: 【问题解决】SSM-@Transactional注解事务无效探讨

Spring SpringMVC MyBatis框架中-@Transactional注解事务无效解决方法


SpringMVC-Spring-MyBatis框架

数据库:SQL SERVER 2008

以前都是用的MySQL数据库,没有出现这个问题,现在换成sql server了,结果事务没有起作用了。


经过一番测试:

排除以下几个问题:

1.数据库原因,不存在的。MySQL中只有InnoDB引擎支持事务。SqlServer2008的企业版作为收费数据库,不可能不支持事务操作。

2.异常类型不是unchecked异常,我写的异常是1/0,为了保险起见,我还抛出RuntimeException试了,结果也是没有回滚。

3.是不是配置文件的没配置好,比如Bean,比如:

    <!-- 配置事物管理类 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dynamicDataSource" />
    </bean>
    <!-- 开启注解式事物扫描 -->
    <tx:annotation-driven transaction-manager="transactionManager"  />


检查几遍,排除这个原因。

4.还有一种情况,因为我以前写的都是对一个数据库的操作,现在是一个数据源多个数据库操作,当时有点怀疑我是不是少配置了什么,导致多数据库时无法启动事务,于是便还原到一个数据库,结果事务还是无效,排除此问题


经过一番折腾,在网上找到一篇文章,说原因是applicationContext.xml的父容器先于Servlet的子容器生效,将Service提前加载了。


于是验证了一下,首先去掉Service实现类的@Service注解,在spring.xml(也就是applicationContext.xml,我起名是spring.xml),配置该类的Bean:


<bean id="sysUserServiceImp" class="cn.kx59.user.service.imp.SysUserServiceImp"></bean>


结果运行之后,事务起作用了。


原因如下:

Spring容器优先加载由ServletContextListener(对应applicationContext.xml,我这里是spring.xml)产生的父容器,而SpringMVC(对应spring-mvc.xml)产生的是子容器。

子容器Controller进行扫描装配时装配的@Service注解的实例是没有经过事务加强处理,即没有事务处理能力的Service,而父容器进行初始化的Service是保证事务的增强处理能力的。如果不在子容器中将Service exclude掉,此时得到的将是原样的无事务处理能力的Service。

所以我们要在扫描的时候在子容器中将Service exclude掉就好了。


也就是在spring-mvc.xml中进行如下修改:


<!--扫描Controller-->
    <context:component-scan base-package="cn.kx59">
        <context:include-filter type="annotation"
                                expression="org.springframework.stereotype.Controller" />
        <!--下面这个是防止事务没起作用,spring.xml的父容器先于Servlet的子容器生效,将Service提前加载了。这里不用再进行加载装配-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
    </context:component-scan>


注意: 请将@Transactional注解写在实现类的方法或类上!不建议写在接口类中!

Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。


在以上解决方法中,若将@Transactional 注解写在接口上,则无法实现事务。所以请将 @Transactional 注解写在实现类中!


目录
相关文章
|
6月前
ssm使用全注解实现增删改查案例——showEmp.jsp
ssm使用全注解实现增删改查案例——showEmp.jsp
|
6月前
ssm使用全注解实现增删改查案例——showDept.jsp
ssm使用全注解实现增删改查案例——showDept.jsp
|
6月前
ssm使用全注解实现增删改查案例——web.xml
ssm使用全注解实现增删改查案例——web.xml
|
6月前
ssm使用全注解实现增删改查案例——updateEmp.jsp
ssm使用全注解实现增删改查案例——updateDept.jsp
|
6月前
ssm使用全注解实现增删改查案例——saveEmp.jsp
ssm使用全注解实现增删改查案例——saveEmp.jsp
|
5月前
|
缓存 NoSQL Java
在 SSM 架构(Spring + SpringMVC + MyBatis)中,可以通过 Spring 的注解式缓存来实现 Redis 缓存功能
【6月更文挑战第18天】在SSM(Spring+SpringMVC+MyBatis)中集成Redis缓存,涉及以下步骤:添加Spring Boot的`spring-boot-starter-data-redis`依赖;配置Redis连接池(如JedisPoolConfig)和连接工厂;在Service层使用`@Cacheable`注解标记缓存方法,指定缓存名和键生成策略;最后,在主配置类启用缓存注解。通过这些步骤,可以利用Spring的注解实现Redis缓存。
79 2
|
6月前
|
JavaScript Java 测试技术
基于ssm+vue.js的个人事务管理系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js的个人事务管理系统附带文章和源代码设计说明文档ppt
43 2
|
6月前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的班级事务管理系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的班级事务管理系统附带文章和源代码设计说明文档ppt
32 1
|
6月前
|
JavaScript Java 测试技术
Java项目基于ssm+vue.js的校园事务自助指南服务系统附带文章和源代码设计说明文档ppt
Java项目基于ssm+vue.js的校园事务自助指南服务系统附带文章和源代码设计说明文档ppt
31 0
|
3月前
|
Java 数据库连接 Maven
手把手教你如何搭建SSM框架、图书商城系统案例
这篇文章是关于如何搭建SSM框架以及实现一个图书商城系统的详细教程,包括了项目的配置文件整合、依赖管理、项目结构和运行效果展示,并提供了GitHub源码链接。
手把手教你如何搭建SSM框架、图书商城系统案例