美文网首页Spring框架学习
Spring声明式事务为何不回滚---探究

Spring声明式事务为何不回滚---探究

作者: ___TheOne___ | 来源:发表于2018-09-14 08:29 被阅读28次

    1.spring事务不回滚的两个原因

    总结一下导致事务不回滚的两个原因:一是Service类内部方法调用,二是try...catch异常。
    详细内容请见Spring声明式事务为何不回滚

    2.Spring声明式事务配置 + SpringDataJPA 测试

    使用代码测试 + 结合控制台debug日志,探究AOP在service方法添加事务细节。

    声明式事务xml配置,spring-data-jpa.xml

    <!-- Jpa事务管理器 start-->
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory"/>
        </bean>
        <!-- Jpa事务管理器 end-->
    
        <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
            <!-- 配置详细事务处理语义 -->
            <tx:attributes>
                <tx:method name="add*" propagation="REQUIRED"/>
                <tx:method name="save*" propagation="REQUIRED"/>
                <tx:method name="insert*" propagation="REQUIRED"/>
                <tx:method name="del*" propagation="REQUIRED"/>
                <tx:method name="update*" propagation="REQUIRED"/>
                <tx:method name="new*" propagation="REQUIRED"/>
    
                <tx:method name="get*" read-only="true" propagation="REQUIRED"/>
                <tx:method name="query*" read-only="true" propagation="REQUIRED"/>
                <tx:method name="find*" read-only="true" propagation="REQUIRED"/>
    
                <tx:method name="*" propagation="SUPPORTS" rollback-for="Exception" read-only="true"/>
            </tx:attributes>
        </tx:advice>
    
        <aop:config>  <!--expose-proxy="true" proxy-target-class="true"-->
            <aop:pointcut id="transactionPointcut"
                          expression="execution(* org.jaden..service..*.*(..))"/>
            <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice"/>
        </aop:config>
    

    Part1:(正确做法)Service类内部方法调用,但是保证外围方法加上事务
    答:外围方法通过xml声明式事务配置加上事务,即第一条标注(------)的日志展示的;当执行到内部方法时,Spring发现当前线程已有事务,因为事务级别是required,就加入当前事务执行。即:日志展示的"JpaTransactionManager:476 - Participating in existing transaction"。这样便能保证事务完整性,能够正常回滚。

    15:07:38,676 DEBUG http-nio-8080-exec-5 servlet.DispatcherServlet:869 - DispatcherServlet with name 'dispatcher' processing GET request for [/trans/noRollback]
    15:07:38,677 DEBUG http-nio-8080-exec-5 annotation.RequestMappingHandlerMapping:310 - Looking up handler method for path /trans/noRollback
    15:07:38,677 DEBUG http-nio-8080-exec-5 annotation.RequestMappingHandlerMapping:317 - Returning handler method [public void org.jaden.jpa.controller.TransNoRollbackController.booksList(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]
    15:07:38,677 DEBUG http-nio-8080-exec-5 support.DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'transNoRollbackController'
    15:07:38,677 DEBUG http-nio-8080-exec-5 servlet.DispatcherServlet:955 - Last-Modified value for [/trans/noRollback] is: -1
    
    ------15:07:38,678 DEBUG http-nio-8080-exec-5 jpa.JpaTransactionManager:367 - Creating new transaction with name [org.jaden.jpa.service.transactionNoRollback.TransNoRollbackService.updateSynBooks]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT------
    
    15:07:38,678 DEBUG http-nio-8080-exec-5 jpa.JpaTransactionManager:371 - Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1a308fab] for JPA transaction
    15:07:38,679 DEBUG http-nio-8080-exec-5 spi.AbstractTransactionImpl:160 - begin
    15:07:38,679 DEBUG http-nio-8080-exec-5 internal.LogicalConnectionImpl:226 - Obtaining JDBC connection
    15:07:38,679 DEBUG http-nio-8080-exec-5 internal.LogicalConnectionImpl:232 - Obtained JDBC connection
    15:07:38,680 DEBUG http-nio-8080-exec-5 jdbc.JdbcTransaction:69 - initial autocommit status: true
    15:07:38,680 DEBUG http-nio-8080-exec-5 jdbc.JdbcTransaction:71 - disabling autocommit
    15:07:38,681 DEBUG http-nio-8080-exec-5 jpa.JpaTransactionManager:403 - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7d4aa0b]
    ------15:07:38,681 DEBUG http-nio-8080-exec-5 jpa.JpaTransactionManager:334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1a308fab] for JPA transaction------
    
    
    ------15:07:38,681 DEBUG http-nio-8080-exec-5 jpa.JpaTransactionManager:476 - Participating in existing transaction------
    
    15:07:38,682 DEBUG http-nio-8080-exec-5 spi.ActionQueue:194 - Executing identity-insert immediately
    15:07:38,683 DEBUG http-nio-8080-exec-5 hibernate.SQL:109 - 
        insert 
        into
            books
            (author, create_time, description, name, price, update_time) 
        values
            (?, ?, ?, ?, ?, ?)
    

    Part2:Service类内部方法调用---导致的事务未回滚(前提是外围方法不加事务)
    答:第三条标注的日志行信息,JpaTransactionManager:869 - Should roll back transaction but cannot - no transaction available

    
    *********************************Condition2:方法A没有事务,方法B有事务:无法按照预期回滚,有可能导致数据库数据不一致。*********************************
    
    
    ------16:02:47,977 DEBUG http-nio-8080-exec-3 support.TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionAttributeSource:351 - Adding transactional method 'save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''------
    
    16:02:47,988 DEBUG http-nio-8080-exec-3 support.DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'transactionManager'
    ------16:02:47,993 DEBUG http-nio-8080-exec-3 jpa.JpaTransactionManager:367 - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''------
    16:02:47,998 DEBUG http-nio-8080-exec-3 jpa.JpaTransactionManager:371 - Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@2101e4dc] for JPA transaction
    16:02:48,013 DEBUG http-nio-8080-exec-3 spi.AbstractTransactionImpl:160 - begin
    16:02:48,019 DEBUG http-nio-8080-exec-3 internal.LogicalConnectionImpl:226 - Obtaining JDBC connection
    16:02:48,028 DEBUG http-nio-8080-exec-3 internal.LogicalConnectionImpl:232 - Obtained JDBC connection
    16:02:48,034 DEBUG http-nio-8080-exec-3 jdbc.JdbcTransaction:69 - initial autocommit status: true
    16:02:48,040 DEBUG http-nio-8080-exec-3 jdbc.JdbcTransaction:71 - disabling autocommit
    16:02:48,053 DEBUG http-nio-8080-exec-3 jpa.JpaTransactionManager:403 - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@b858432]
    16:02:48,174 DEBUG http-nio-8080-exec-3 spi.ActionQueue:194 - Executing identity-insert immediately
    16:02:48,218 DEBUG http-nio-8080-exec-3 hibernate.SQL:109 - 
        insert 
        into
            books
            (author, create_time, description, name, price, update_time) 
        values
            (?, ?, ?, ?, ?, ?)
    Hibernate: 
        insert 
        into
            books
            (author, create_time, description, name, price, update_time) 
        values
            (?, ?, ?, ?, ?, ?)
    16:02:48,325 DEBUG http-nio-8080-exec-3 id.IdentifierGeneratorHelper:94 - Natively generated identity: 32
    16:02:48,336 DEBUG http-nio-8080-exec-3 pool.PreparedStatementPool:121 - {conn-10005, pstmt-20000} enter cache
    16:02:48,362 DEBUG http-nio-8080-exec-3 jpa.JpaTransactionManager:759 - Initiating transaction commit
    16:02:48,366 DEBUG http-nio-8080-exec-3 jpa.JpaTransactionManager:512 - Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@2101e4dc]
    16:02:48,370 DEBUG http-nio-8080-exec-3 spi.AbstractTransactionImpl:175 - committing
    16:02:48,377 DEBUG http-nio-8080-exec-3 internal.AbstractFlushingEventListener:149 - Processing flush-time cascades
    16:02:48,385 DEBUG http-nio-8080-exec-3 internal.AbstractFlushingEventListener:189 - Dirty checking collections
    16:02:48,401 DEBUG http-nio-8080-exec-3 internal.AbstractFlushingEventListener:123 - Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
    16:02:48,407 DEBUG http-nio-8080-exec-3 internal.AbstractFlushingEventListener:130 - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
    16:02:48,423 DEBUG http-nio-8080-exec-3 util.EntityPrinter:114 - Listing entities:
    16:02:48,428 DEBUG http-nio-8080-exec-3 util.EntityPrinter:121 - org.jaden.jpa.entity.Books{createTime=Wed Sep 12 16:02:38 CST 2018, author=null, price=null, name=Spring事务未回滚研究111, description=好好学习,天天向上, updateTime=null, id=32}
    16:02:48,435 DEBUG http-nio-8080-exec-3 jdbc.JdbcTransaction:113 - committed JDBC Connection
    16:02:48,439 DEBUG http-nio-8080-exec-3 jdbc.JdbcTransaction:126 - re-enabling autocommit
    16:02:48,447 DEBUG http-nio-8080-exec-3 jpa.JpaTransactionManager:600 - Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@2101e4dc] after transaction
    16:02:48,451 DEBUG http-nio-8080-exec-3 jpa.EntityManagerFactoryUtils:435 - Closing JPA EntityManager
    16:02:48,456 DEBUG http-nio-8080-exec-3 internal.LogicalConnectionImpl:246 - Releasing JDBC connection
    16:02:48,461 DEBUG http-nio-8080-exec-3 internal.LogicalConnectionImpl:264 - Released JDBC connection
    16:02:48,468 DEBUG http-nio-8080-exec-3 jpa.JpaTransactionManager:1021 - Resuming suspended transaction after completion of inner transaction
    
    ------16:03:00,788 DEBUG http-nio-8080-exec-3 jpa.JpaTransactionManager:869 - Should roll back transaction but cannot - no transaction available------
    
    16:03:00,798 DEBUG http-nio-8080-exec-3 annotation.ExceptionHandlerExceptionResolver:133 - Resolving exception from handler [public void org.jaden.jpa.controller.TransNoRollbackController.booksList(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    

    Part3:try-catch异常---导致的事务未回滚
    答:在默认配置中,Spring FrameWork 的事务框架代码只会将出现runtime, unchecked 异常的事务标记为回滚;也就是说事务中抛出的异常时RuntimeException或者是其子类,这样事务才会回滚(默认情况下Error也会导致事务回滚)。在默认配置的情况下,所有的 checked 异常都不会引起事务回滚。

    将rollback-for,更改为MyCheckedException。让checkedException也可以回滚

    ------18:39:18,869 DEBUG http-nio-8080-exec-4 jpa.JpaTransactionManager:367 - Creating new transaction with name [org.jaden.jpa.service.transactionNoRollback.TransNoRollbackService.addBookHaveException]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-MyCheckedException------
    18:39:18,874 DEBUG http-nio-8080-exec-4 jpa.JpaTransactionManager:371 - Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@2bc93598] for JPA transaction
    18:39:18,889 DEBUG http-nio-8080-exec-4 spi.AbstractTransactionImpl:160 - begin
    18:39:18,893 DEBUG http-nio-8080-exec-4 internal.LogicalConnectionImpl:226 - Obtaining JDBC connection
    18:39:18,897 DEBUG http-nio-8080-exec-4 internal.LogicalConnectionImpl:232 - Obtained JDBC connection
    18:39:18,902 DEBUG http-nio-8080-exec-4 jdbc.JdbcTransaction:69 - initial autocommit status: true
    18:39:18,906 DEBUG http-nio-8080-exec-4 jdbc.JdbcTransaction:71 - disabling autocommit
    18:39:18,917 DEBUG http-nio-8080-exec-4 jpa.JpaTransactionManager:403 - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@202aace7]
    18:39:19,458 DEBUG http-nio-8080-exec-4 support.TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionAttributeSource:351 - Adding transactional method 'save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
    18:39:19,469 DEBUG http-nio-8080-exec-4 support.DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'transactionManager'
    18:39:19,474 DEBUG http-nio-8080-exec-4 jpa.JpaTransactionManager:334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@2bc93598] for JPA transaction
    18:39:19,479 DEBUG http-nio-8080-exec-4 jpa.JpaTransactionManager:476 - Participating in existing transaction
    18:39:19,588 DEBUG http-nio-8080-exec-4 spi.ActionQueue:194 - Executing identity-insert immediately
    18:39:19,634 DEBUG http-nio-8080-exec-4 hibernate.SQL:109 - 
        insert 
        into
            books
            (author, create_time, description, name, price, update_time) 
        values
            (?, ?, ?, ?, ?, ?)
    Hibernate: 
        insert 
        into
            books
            (author, create_time, description, name, price, update_time) 
        values
            (?, ?, ?, ?, ?, ?)
    18:39:19,739 DEBUG http-nio-8080-exec-4 id.IdentifierGeneratorHelper:94 - Natively generated identity: 37
    18:39:19,750 DEBUG http-nio-8080-exec-4 pool.PreparedStatementPool:121 - {conn-10005, pstmt-20000} enter cache
    18:39:34,565 DEBUG http-nio-8080-exec-4 jpa.JpaTransactionManager:851 - Initiating transaction rollback
    ------18:39:34,565 DEBUG http-nio-8080-exec-4 jpa.JpaTransactionManager:538 - Rolling back JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@2bc93598]------
    ------18:39:34,565 DEBUG http-nio-8080-exec-4 spi.AbstractTransactionImpl:205 - rolling back------
    18:39:34,572 DEBUG http-nio-8080-exec-4 jdbc.JdbcTransaction:164 - rolled JDBC Connection
    18:39:34,572 DEBUG http-nio-8080-exec-4 jdbc.JdbcTransaction:126 - re-enabling autocommit
    18:39:34,575 DEBUG http-nio-8080-exec-4 jpa.JpaTransactionManager:600 - Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@2bc93598] after transaction
    18:39:34,575 DEBUG http-nio-8080-exec-4 jpa.EntityManagerFactoryUtils:435 - Closing JPA EntityManager
    18:39:34,576 DEBUG http-nio-8080-exec-4 internal.LogicalConnectionImpl:246 - Releasing JDBC connection
    18:39:34,576 DEBUG http-nio-8080-exec-4 internal.LogicalConnectionImpl:264 - Released JDBC connection
    org.jaden.jpa.service.transactionNoRollback.MyCheckedException
    
    

    3.精华文章参考

    1.Spring声明式事务为何不回滚
    2.关于 Spring 事务注解的几个不能忽视的细节

    相关文章

      网友评论

        本文标题:Spring声明式事务为何不回滚---探究

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