☆Spring MVC + Mybatis + Spring A

作者: 七寸知架构 | 来源:发表于2016-12-15 14:02 被阅读416次

1 问题描述

在最近的一个项目中,采用springMVC、mybatis,发现一个很恼人的问题:事务管理不起作用!!网上查阅了大量的资料,尝试了各种解决办法,亦未能解决问题!

applicationContext.xml配置:

<context:annotation-config />
<!-- 引入jdbc属性配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />   
<!-- 数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean> 
<bean id="ftpConfig" class="com.wtas.utils.CustomizedPropertyConfig">   
    <property name="location" value="classpath:ftp.properties" />
</bean>

<!-- 配置mybatis用到的sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="configLocation" value="classpath:mybatisConfig.xml" />
    <property name="dataSource" ref="dataSource" />
    <property name="typeAliasesPackage" value="com.wtas.study.domain,com.wtas.studygroup.domain,com.wtas.sys.domain,com.wtas.test.domain" />
    <property name="mapperLocations" value="classpath*:com/wtas/**/*Mapper.xml" />
</bean>
<!-- 根据映射文件动态生成dao的实现 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.wtas" />
    <property name="annotationClass" value="org.springframework.stereotype.Repository" />
</bean>
<!-- 事务控制 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>
<tx:advice id="userTxAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="remove*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" />
        <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" />
        <tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />
        <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />
        <tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />
        <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
        <tx:method name="publish*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
        <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="list*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="query*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="page*" propagation="SUPPORTS" read-only="true" />
    </tx:attributes>
</tx:advice>
<tx:annotation-driven transaction-manager="transactionManager"/>
    <!-- execution(public * com.wtas.*.service.*.*(..)) OR   execution(public * com.wtas.*.*.*.service.*.*(..))-->
<aop:config>
    <aop:pointcut id="pc" expression="execution(public * com.wtas.*.service.*.*(..))" />
    <aop:advisor pointcut-ref="pc" advice-ref="userTxAdvice" />
</aop:config>

springMVC.xml配置:

<!-- 这里注册转换器 -->
<mvc:annotation-driven conversion-service="conversionService" />
        <context:component-scan base-package="com.wtas"></context:component-scan>
<mvc:default-servlet-handler />

<!-- 注册ConversionService -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <!-- 转换器 -->
    <property name="converters">
        <list>
            <bean class="com.wtas.converter.StringToDateConverter">
                <constructor-arg value="yyyy-MM-dd" />
            </bean>
        </list>
    </property>
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <list>
                <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter" />
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
        </list>
    </property>
</bean>

<!-- 视图解释类 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsps/" />
    <property name="suffix" value=".jsp" />
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>

2 排查过程

具体原理,请参考:深入分析Spring与Spring MVC容器

3 解决问题

applicationContext.xml中添加:

<context:component-scan base-package="com.wtas">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> 
</context:component-scan>

springMVC.xml中修改:

<!-- 扫描所有的controller 但是不扫描service-->  
<context:component-scan base-package="com.wtas">  
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />  
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />  
</context:component-scan>  

4 总结问题

具体总结,可参见http://my.oschina.net/xianggao/blog/522267#OSC_h1_4

相关文章

网友评论

  • a3b65c108416:你好,想请教一下。
    今天service回滚失败,断点发现,spring aop确实是设置了autoCommit为false,但是到真正insert数据的时候,autoCommit又变成了true,导致事物没开起,后面的一系列回归操作也就失败了。
    后来aop设置autoCommit的connect和insert的时候用的connect不是一个实例。
    所以想问下是不是因为两个connect不是同一个实例导致的回滚失败。
    七寸知架构:@大火燎原 1. 是否切换数据源了?2. 是否切换线程了?可以加我微信 代码我看下 15010244158
    a3b65c108416: @陶邦仁 发现aop的时候通过datasource为从ConnectionHolder里取Connection,而MyBatis在insert的时候,却是通过SessionFactory从ConnectionHolder里获取Connection,这次取出来的Connection是Null,所以又从datasouce里取了新的Connection。

    然后想问下,大概会有哪些原因会使spring事务在aop和mybatis里取到的connection不是同一个呢?
    七寸知架构:@大火燎原 是的,事务是不能夸两个不同的Connection的,夸了两个不同的Connection就是分布式事务了。

本文标题:☆Spring MVC + Mybatis + Spring A

本文链接:https://www.haomeiwen.com/subject/oyfgmttx.html