美文网首页
spring事务传播机制

spring事务传播机制

作者: smallAttr | 来源:发表于2019-01-10 15:24 被阅读0次

    问题描述

    最近在项目优化过程中,遇到一个问题:因为前段时间把一个功能单拎出来弄成一个项目,这次优化就是实现代码的解耦,所以相关逻辑代码删除并通过HTTP的方式调用。完成代码优化后,通过jmeter run testCases。发现根据主键ID查询数据返回NULL。


    流程图

    分析过程

    1. 当发现这个问题,我第一反应会不会是RPC调用出现问题了,查看日志发现不是想象这样,而是实实在在的查询结果为NULL。
    2. 查看代码逻辑,插入逻辑和查询逻辑放在一个大方法里面,大概定位是因为事务没有提交,数据还未持久化到数据库中,进而查看配置文件,关于事务配置。如下:
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
    </bean>
    <aop:config>
            <aop:pointcut id="pointcut"  expression="execution(* com.github.smallAttr.*.service.*.*(..)) || execution(* com.github.smallAttr.*.business.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!-- the transactional semantics... -->
            <tx:attributes>
                <!-- all methods starting with 'get' are read-only -->
                <!--<tx:method name="get*" read-only="true"/>-->
                <!-- other methods use the default transaction settings (see below) -->
                <tx:method name="*"/>
            </tx:attributes>
    </tx:advice>
    

    果然直接在类上面声明事务(说明:相当于在该类所有public方法上加上@Transcational注解),进而证实了刚才的猜想。

    我感觉这样的配置真的不是最佳实践。不需要的地方也加上了。正常情况下,事务传播机制保证只有外层事务生效,但是总给人的感觉是代码不可控。尤其是遇到特殊情况下,这很难修改,要满足情况,代码写得很丑陋,还得写上一大堆注释,以防后续partner给修改了。

    解决方案

    插入逻辑新启一个事务Propagation.REQUIRES_NEW,保证数据持久化再查询。

    这实际修改过程中,也是走了不少弯路

    1. 同一个类中,事务声明 REQUIRES -> REQUIRES_NEW,事务未生效。
    2. REQUIRES -> REQUIRES_NEW处于不同类中(REQUIRES_NEW所在的方法未实现接口),事务未生效。
    3. REQUIRES -> REQUIRES_NEW处于不同类中(REQUIRES_NEW所在的方法实现接口),事务生效。

    说实话,虽然问题得一解决,但是在这过程中还是存在很多疑点,时间空闲点我会好好梳理下并证实。

    查找问题过程中,发现这两篇文章不错:

    相关文章

      网友评论

          本文标题:spring事务传播机制

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