美文网首页
Spring事务失效的几种原因

Spring事务失效的几种原因

作者: 平凡的柚子 | 来源:发表于2021-01-23 19:36 被阅读0次

    数据库引擎不支持事务

    在MySQL数据库中有几种引擎(InnoDB,MyISAM,Memory等等),仅仅InnoDB支持事务,如果数据库底层都不支持事务的话,那么再怎么折腾都是白搭.

    @transactional加在private方法上

    @Transactional只能加在public方法上,如果需要在private方法中加入事务,可以使用Aspect配transactionManager使用.

    本类方法调本类另一个方法
    例如:

    @Service
    public class UserServiceImpl implements UserService {
    
      @Transactional
      public void update(User user) {
      //check
        updateUserInfo(user);
      }
    
      @Transactional(propagation = Propagation.REQUIRES_NEW)
      public void updateUser(User user) {
        // update user
      }
    
    }
    

    @Transactional(propagation = Propagation.REQUIRES_NEW)是无效的,在Spring中是使用代理的方式实现事务,发生自身调用的时候,没有经过Spring的代理,自然事务失效.

    不支持事务

    @Service
    public class UserServiceImpl implements UserService {
    
      @Transactional(propagation = Propagation.NOT_SUPPORTED)
      public void update(User user) {
      //do some action
      }
    
    }
    

    @Transactional(propagation = Propagation.NOT_SUPPORTED)表示如果当前存在事务就挂起,以没有事务的方式运行,主动不支持事务了,那么再怎么操作也是白搭. 此处贴下Spring的传播行为:

      /**
       * Support a current transaction, create a new one if none exists.
       * Analogous to EJB transaction attribute of the same name.
       * <p>This is the default setting of a transaction annotation.
       */
      REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
    
      /**
       * Support a current transaction, execute non-transactionally if none exists.
       * Analogous to EJB transaction attribute of the same name.
       * <p>Note: For transaction managers with transaction synchronization,
       * PROPAGATION_SUPPORTS is slightly different from no transaction at all,
       * as it defines a transaction scope that synchronization will apply for.
       * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)
       * will be shared for the entire specified scope. Note that this depends on
       * the actual synchronization configuration of the transaction manager.
       * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
       */
      SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
    
      /**
       * Support a current transaction, throw an exception if none exists.
       * Analogous to EJB transaction attribute of the same name.
       */
      MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
    
      /**
       * Create a new transaction, and suspend the current transaction if one exists.
       * Analogous to the EJB transaction attribute of the same name.
       * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
       * on all transaction managers. This in particular applies to
       * {@link org.springframework.transaction.jta.JtaTransactionManager},
       * which requires the {@code javax.transaction.TransactionManager} to be
       * made available to it (which is server-specific in standard Java EE).
       * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
       */
      REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
    
      /**
       * Execute non-transactionally, suspend the current transaction if one exists.
       * Analogous to EJB transaction attribute of the same name.
       * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
       * on all transaction managers. This in particular applies to
       * {@link org.springframework.transaction.jta.JtaTransactionManager},
       * which requires the {@code javax.transaction.TransactionManager} to be
       * made available to it (which is server-specific in standard Java EE).
       * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
       */
      NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
    
      /**
       * Execute non-transactionally, throw an exception if a transaction exists.
       * Analogous to EJB transaction attribute of the same name.
       */
      NEVER(TransactionDefinition.PROPAGATION_NEVER),
    
      /**
       * Execute within a nested transaction if a current transaction exists,
       * behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB.
       * <p>Note: Actual creation of a nested transaction will only work on specific
       * transaction managers. Out of the box, this only applies to the JDBC
       * DataSourceTransactionManager when working on a JDBC 3.0 driver.
       * Some JTA providers might support nested transactions as well.
       * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
       */
      NESTED(TransactionDefinition.PROPAGATION_NESTED);
    

    异常被catch

    @Service
    public class UserServiceImpl implements UserService {
    
      @Transactional
      public void update(User user) {
      try{
    
      }catch(Exception e){
        log.error(e.getMessage(),e);
      }
      }
    
    }
    

    触发回滚的操作是被接收到异常,一般我们会在@Transactional后面加上rollbackFor或者noRollbackForClassName来指明触发回滚的异常,但是如果在代码中给catch了异常,那么对于Spring代理来说就这个方法从头到尾都没有问题,自然不会触发回滚.

    异常类型错误

    @Service
    public class UserServiceImpl implements UserService {
    
      @Transactional
      public void update(User user) {
      try{
    
      }catch(Exception e){
        log.error(e.getMessage(),e);
        throw new Exception(e.getMessage());
      }
      }
    
    }
    

    以上方式throw new Exception(e.getMessage());事务也是无效的,主要原因是事务回滚的条件是throw 运行时异常(RunTimeException).如果需要其他异常也回滚,需要在@Transactional后面加上rollbackFor或者noRollbackForClassName来指明触发回滚的异常.

    没有被Spring管理

    不在Spring环境下,自然不受Spring的管理,事务管理器也当然失去了作用.

    没有配置TransactionManager
    需要对当前数据源配置事务管理器,尤其是在多数据源的情况下.


    最新2020整理收集的一些高频面试题(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友请加Q君样:11604713672

    相关文章

      网友评论

          本文标题:Spring事务失效的几种原因

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