Spring事物失效、无效问题

项目原来的ORM是Hibernate,要改造成MyBatis,相关配置后启动成功,没有报错。

数据库是MySql5.7 表的存储引擎是:InnoDB

但是在测试事物有效性的时候,发现不回滚!!

@Override
public void saveUser(UserVO vo) {
    UserDao.saveUser(vo);
    throw new RuntimeException("事物异常,请回滚吧。");
}

配置如下:

<!-- 启用注解支持 -->
<context:annotation-config/>
<!-- 开启aop注解方式 -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
<!-- ========== Mybatis 配置以及事物的配置 Start ==========-->
<!-- 不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 注入数据源-->
    <property name="dataSource" ref="dataSource" />
    <!-- 自动扫描映射的xml文件 -->
    <property name="mapperLocations" value="classpath:com/xx/*/dao/mapper/*.xml"></property>
</bean>
<!-- 自动扫描映射接口类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    <property name="basePackage" value="com/xx/*/dao"></property>
</bean>

<!-- 配置Spring的事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>
<!-- 拦截器方式配置事物  -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="save*" propagation="REQUIRED" read-only="false" />
        <tx:method name="add*" propagation="REQUIRED" read-only="false" />
        <tx:method name="delete*" propagation="REQUIRED" read-only="false" />
        <tx:method name="update*" propagation="REQUIRED" read-only="false" />
        <tx:method name="edit*" propagation="REQUIRED" read-only="false" />

        <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="export*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="*" propagation="SUPPORTS" read-only="true" />
    </tx:attributes>
</tx:advice>
<aop:config>
    <aop:pointcut id="transactionPointcut" expression="execution(* com.xx.xx.service.impl.*.*(..))" />
    <aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPointcut" />
</aop:config>
<!--支持注解驱动的事务管理,指定默认事务管理器 -->
<tx:annotation-driven order="0" transaction-manager="transactionManager"/>
<!-- ========== Mybatis 配置以及事物的配置 End ==========-->

最终的问题出现在component-scan的顺序上:

大致是这样的场景:

项目中原来使用Spring MVC页面采用JSP。想要优化,但并不打算用其他的模板语言:比如Freemarker、Thymeleaf等。

直接使用HTML文件,多好啊~,后来我想不需要Controller层了!!模板+数据的形式太死板了。HTML+Restful 灵活多了。

直接就是dao、dao.mapper 、service、service.impl、vo

@RequestMapping 就写在了Service实现层

在applicationContext.xml 中配置自动扫描:

<context:component-scan base-package="com.xx">

启动正常,但是url访问却是404。(;′⌒`)

于是将这段扫描配置移至spring-mvc.xml,能够正常访问了。 但是Spring的事物失效了!!

web.xml中的配置:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

spring-mvc.xml后面加载的,所以事物的特性被覆盖了。

最终还是使用了,dao、dao.mapper、service、service.impl、controller、vo的结构。

service在applicationContext.xml中扫描,事物也是配置在这个xml文件里面的。

<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com">
    <!-- 扫描时跳过 @Controller 注解的JAVA类(控制器) -->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

controller在spring-mvc.xml中扫描

<!-- controller类支持事物@Transactional -->
<tx:annotation-driven/>

<!--而在springMVC配置文件中将Service注解给去掉-->
<context:component-scan base-package="com">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
</context:component-scan>

问题解决,测试事物成功。

controller层,也支持事物,使用注解形式配合,很棒。示例如下:

@Transactional
@ResponseBody
@RequestMapping(value = "/saveUser", method = RequestMethod.GET)
public void saveUser() throws IOException {
    Uservo = new Uservo();
    vo.setUserName("很好");
    vo.setUserBirthday(new Date());
    vo.setUserId("6");
    vo.setUserSalary(500d);
    userService.saveUser(vo);

    vo.setUserId("7");
    userService.saveUser(vo);
    throw new RuntimeException("事物异常,请回滚吧。");
}

后来仔细想了想,代码的分层。还是有意义的。controller可以处理页面逻辑,比如参数接收、处理、url映射这些偏页面的逻辑。service层则更加注重业务逻辑处理。这样分开也是很好的。

猜你喜欢

转载自blog.csdn.net/Cky079/article/details/83001954