深入浅出Spring的tx事务基本概念:事务属性与事务隔离级别

文章目录

1.概述

1.事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)2.特点:事务是恢复和并发控制的基本单位。

2.事务的属性:ACID

2.1.原子性:Automicity

2.2.一致性:Consistency

1.事务必须是使数据库从一个一致性状态变到另一个一致性状态。 主要是数据库落的数据必须跟我们实际提交的数据是一致的;
2.一致性与原子性是密切相关的。

2.3.隔离性:Isolation

1.事物的隔离性主要指的是事务与事务之间是相互隔离,互不影响的;

2.4.持久性:Durability

 指一个事务一旦提交,它 对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何 影响。

3.事务的传播机制

3.1.背景问题

比如,我们在ServiceA中, 同时有两个涉及事务的方法:methodA和methodB
1.methordA提交成功,methodB提交失败,那么methodA需不需要回滚?
2.

3.2.事务传播机制的概述

1.事务传播机制本质上解决的是同一个Service中,存在的事务提交可能多个;
  对于这种多个事务的处理,我们如何处理的问题;

3.3.事务传播机制的类型Code:TransactionDefinition

/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.transaction;

import java.sql.Connection;

import org.springframework.lang.Nullable;

/**
* Interface that defines Spring-compliant transaction properties.
* Based on the propagation behavior definitions analogous to EJB CMT attributes.
*
* <p>Note that isolation level and timeout settings will not get applied unless
* an actual new transaction gets started. As only {@link #PROPAGATION_REQUIRED},
* {@link #PROPAGATION_REQUIRES_NEW} and {@link #PROPAGATION_NESTED} can cause
* that, it usually doesn't make sense to specify those settings in other cases.
* Furthermore, be aware that not all transaction managers will support those
* advanced features and thus might throw corresponding exceptions when given
* non-default values.
*
* <p>The {@link #isReadOnly() read-only flag} applies to any transaction context,
* whether backed by an actual resource transaction or operating non-transactionally
* at the resource level. In the latter case, the flag will only apply to managed
* resources within the application, such as a Hibernate {@code Session}.
*
* @author Juergen Hoeller
* @since 08.05.2003
* @see PlatformTransactionManager#getTransaction(TransactionDefinition)
* @see org.springframework.transaction.support.DefaultTransactionDefinition
* @see org.springframework.transaction.interceptor.TransactionAttribute
*/
public interface TransactionDefinition {

   /**
    * Support a current transaction; create a new one if none exists.
    * Analogous to the EJB transaction attribute of the same name.
    * <p>This is typically the default setting of a transaction definition,
    * and typically defines a transaction synchronization scope.
    */
   int PROPAGATION_REQUIRED = 0;

   /**
    * Support a current transaction; execute non-transactionally if none exists.
    * Analogous to the EJB transaction attribute of the same name.
    * <p><b>NOTE:</b> For transaction managers with transaction synchronization,
    * {@code PROPAGATION_SUPPORTS} is slightly different from no transaction
    * at all, as it defines a transaction scope that synchronization might apply to.
    * As a consequence, the same resources (a JDBC {@code Connection}, a
    * Hibernate {@code Session}, etc) will be shared for the entire specified
    * scope. Note that the exact behavior depends on the actual synchronization
    * configuration of the transaction manager!
    * <p>In general, use {@code PROPAGATION_SUPPORTS} with care! In particular, do
    * not rely on {@code PROPAGATION_REQUIRED} or {@code PROPAGATION_REQUIRES_NEW}
    * <i>within</i> a {@code PROPAGATION_SUPPORTS} scope (which may lead to
    * synchronization conflicts at runtime). If such nesting is unavoidable, make sure
    * to configure your transaction manager appropriately (typically switching to
    * "synchronization on actual transaction").
    * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
    * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
    */
   int PROPAGATION_SUPPORTS = 1;

   /**
    * Support a current transaction; throw an exception if no current transaction
    * exists. Analogous to the EJB transaction attribute of the same name.
    * <p>Note that transaction synchronization within a {@code PROPAGATION_MANDATORY}
    * scope will always be driven by the surrounding transaction.
    */
   int PROPAGATION_MANDATORY = 2;

   /**
    * Create a new transaction, suspending 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 it to it (which is server-specific in standard Java EE).
    * <p>A {@code PROPAGATION_REQUIRES_NEW} scope always defines its own
    * transaction synchronizations. Existing synchronizations will be suspended
    * and resumed appropriately.
    * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
    */
   int PROPAGATION_REQUIRES_NEW = 3;

   /**
    * Do not support a current transaction; rather always execute non-transactionally.
    * 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 it to it (which is server-specific in standard Java EE).
    * <p>Note that transaction synchronization is <i>not</i> available within a
    * {@code PROPAGATION_NOT_SUPPORTED} scope. Existing synchronizations
    * will be suspended and resumed appropriately.
    * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
    */
   int PROPAGATION_NOT_SUPPORTED = 4;

   /**
    * Do not support a current transaction; throw an exception if a current transaction
    * exists. Analogous to the EJB transaction attribute of the same name.
    * <p>Note that transaction synchronization is <i>not</i> available within a
    * {@code PROPAGATION_NEVER} scope.
    */
   int PROPAGATION_NEVER = 5;

   /**
    * Execute within a nested transaction if a current transaction exists,
    * behave like {@link #PROPAGATION_REQUIRED} else. There is no analogous
    * feature in EJB.
    * <p><b>NOTE:</b> Actual creation of a nested transaction will only work on
    * specific transaction managers. Out of the box, this only applies to the JDBC
    * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
    * when working on a JDBC 3.0 driver. Some JTA providers might support
    * nested transactions as well.
    * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
    */
   int PROPAGATION_NESTED = 6;


   /**
    * Use the default isolation level of the underlying datastore.
    * All other levels correspond to the JDBC isolation levels.
    * @see java.sql.Connection
    */
   int ISOLATION_DEFAULT = -1;

   /**
    * Indicates that dirty reads, non-repeatable reads and phantom reads
    * can occur.
    * <p>This level allows a row changed by one transaction to be read by another
    * transaction before any changes in that row have been committed (a "dirty read").
    * If any of the changes are rolled back, the second transaction will have
    * retrieved an invalid row.
    * @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
    */
   int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;

   /**
    * Indicates that dirty reads are prevented; non-repeatable reads and
    * phantom reads can occur.
    * <p>This level only prohibits a transaction from reading a row
    * with uncommitted changes in it.
    * @see java.sql.Connection#TRANSACTION_READ_COMMITTED
    */
   int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;

   /**
    * Indicates that dirty reads and non-repeatable reads are prevented;
    * phantom reads can occur.
    * <p>This level prohibits a transaction from reading a row with uncommitted changes
    * in it, and it also prohibits the situation where one transaction reads a row,
    * a second transaction alters the row, and the first transaction re-reads the row,
    * getting different values the second time (a "non-repeatable read").
    * @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
    */
   int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;

   /**
    * Indicates that dirty reads, non-repeatable reads and phantom reads
    * are prevented.
    * <p>This level includes the prohibitions in {@link #ISOLATION_REPEATABLE_READ}
    * and further prohibits the situation where one transaction reads all rows that
    * satisfy a {@code WHERE} condition, a second transaction inserts a row
    * that satisfies that {@code WHERE} condition, and the first transaction
    * re-reads for the same condition, retrieving the additional "phantom" row
    * in the second read.
    * @see java.sql.Connection#TRANSACTION_SERIALIZABLE
    */
   int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;


   /**
    * Use the default timeout of the underlying transaction system,
    * or none if timeouts are not supported.
    */
   int TIMEOUT_DEFAULT = -1;


   /**
    * Return the propagation behavior.
    * <p>Must return one of the {@code PROPAGATION_XXX} constants
    * defined on {@link TransactionDefinition this interface}.
    * @return the propagation behavior
    * @see #PROPAGATION_REQUIRED
    * @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()
    */
   int getPropagationBehavior();

   /**
    * Return the isolation level.
    * <p>Must return one of the {@code ISOLATION_XXX} constants
    * defined on {@link TransactionDefinition this interface}.
    * <p>Only makes sense in combination with {@link #PROPAGATION_REQUIRED}
    * or {@link #PROPAGATION_REQUIRES_NEW}.
    * <p>Note that a transaction manager that does not support custom isolation levels
    * will throw an exception when given any other level than {@link #ISOLATION_DEFAULT}.
    * @return the isolation level
    */
   int getIsolationLevel();

   /**
    * Return the transaction timeout.
    * <p>Must return a number of seconds, or {@link #TIMEOUT_DEFAULT}.
    * <p>Only makes sense in combination with {@link #PROPAGATION_REQUIRED}
    * or {@link #PROPAGATION_REQUIRES_NEW}.
    * <p>Note that a transaction manager that does not support timeouts will throw
    * an exception when given any other timeout than {@link #TIMEOUT_DEFAULT}.
    * @return the transaction timeout
    */
   int getTimeout();

   /**
    * Return whether to optimize as a read-only transaction.
    * <p>The read-only flag applies to any transaction context, whether
    * backed by an actual resource transaction
    * ({@link #PROPAGATION_REQUIRED}/{@link #PROPAGATION_REQUIRES_NEW}) or
    * operating non-transactionally at the resource level
    * ({@link #PROPAGATION_SUPPORTS}). In the latter case, the flag will
    * only apply to managed resources within the application, such as a
    * Hibernate {@code Session}.
    * <p>This just serves as a hint for the actual transaction subsystem;
    * it will <i>not necessarily</i> cause failure of write access attempts.
    * A transaction manager which cannot interpret the read-only hint will
    * <i>not</i> throw an exception when asked for a read-only transaction.
    * @return {@code true} if the transaction is to be optimized as read-only
    * @see org.springframework.transaction.support.TransactionSynchronization#beforeCommit(boolean)
    * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
    */
   boolean isReadOnly();

   /**
    * Return the name of this transaction. Can be {@code null}.
    * <p>This will be used as the transaction name to be shown in a
    * transaction monitor, if applicable (for example, WebLogic's).
    * <p>In case of Spring's declarative transactions, the exposed name will be
    * the {@code fully-qualified class name + "." + method name} (by default).
    * @return the name of this transaction
    * @see org.springframework.transaction.interceptor.TransactionAspectSupport
    * @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionName()
    */
   @Nullable
   String getName();

}

3.4.事务传播机制的类型

3.4.1.PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。(默认)

3.4.1.1.原始数据:User1ServiceImpl
@Service
public class User1ServiceImpl implements User1Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequired(User1 user){
        user1Mapper.insert(user);
    }
}
3.4.1.2.原始数据:User2ServiceImpl
@Service
public class User2ServiceImpl implements User2Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequired(User2 user){
        user2Mapper.insert(user);
    }
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequiredException(User2 user){
        user2Mapper.insert(user);
        throw new RuntimeException();
    }
}
3.4.1.3.场景验证1:外围方法不开启事务,外围方法抛出异常
3.4.1.3.1.Code
@Override
    public void notransaction_exception_required_required(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequired(user2);
        
        throw new RuntimeException();
    }
3.4.1.3.1.总结:

在这里插入图片描述

3.4.1.4.场景验证2:外围方法不开启事务,内部方法抛出异常
3.4.1.4.1.Code:
@Override
    public void notransaction_required_required_exception(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiredException(user2);
    }
3.4.1.4.2.总结:

在这里插入图片描述

3.4.1.5.场景验证3:外围方法开启事务,外部方法抛出异常
3.4.1.5.1.Code
@Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_exception_required_required(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequired(user2);
        
        throw new RuntimeException();
    }
3.4.1.5.1.总结

在这里插入图片描述

3.4.1.6.场景验证4
3.4.1.6.1.Code
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_required_required_exception(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiredException(user2);
    }
3.4.1.6.1.总结

在这里插入图片描述

3.4.1.7.场景验证5
3.4.1.7.1.Code
    @Transactional
    @Override
    public void transaction_required_required_exception_try(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        try {
            user2Service.addRequiredException(user2);
        } catch (Exception e) {
            System.out.println("方法回滚");
        }
    }
3.4.1.7.2.总结

在这里插入图片描述

3.4.1.8.结论
1.结论:通过这两个方法我们证明了在外围方法未开启事务的情况下Propagation.REQUIRED修饰的内部方法会新开启自己的事务,
  且开启的事务相互独立,互不干扰。
2.结论:以上试验结果我们证明在外围方法开启事务的情况下Propagation.REQUIRED修饰的内部方法会加入到外围方法的事务中,
  所有Propagation.REQUIRED修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚。

3.4.2.PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。

1.新建事务,如果当前存在事务,把当前事务挂起。
2.新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,
  内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作
3.4.2.1.原始数据:User1ServiceImpl和User2ServiceImpl

User1ServiceImpl

@Service
public class User1ServiceImpl implements User1Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addRequiresNew(User1 user){
        user1Mapper.insert(user);
    }
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequired(User1 user){
        user1Mapper.insert(user);
    }
}

User2ServiceImpl

@Service
public class User2ServiceImpl implements User2Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addRequiresNew(User2 user){
        user2Mapper.insert(user);
    }
    
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addRequiresNewException(User2 user){
        user2Mapper.insert(user);
        throw new RuntimeException();
    }
}
3.4.2.1.场景验证1:外围方法不开启事务,外围方法抛出异常
3.4.2.1.1.Code
    @Override
    public void notransaction_exception_requiresNew_requiresNew(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequiresNew(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNew(user2);
        throw new RuntimeException();   
    }
3.4.2.1.2.总结

在这里插入图片描述

3.4.2.2.场景验证2:外围不方法开启事务,内部方法抛出异常
3.4.2.2.1.Code
    @Override
    public void notransaction_requiresNew_requiresNew_exception(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequiresNew(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNewException(user2);
    }
3.4.2.1.2.总结

在这里插入图片描述

3.4.2.3.场景验证3:外围方法开启事务,外围方法抛出异常
3.4.2.3.1.Code
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_exception_required_requiresNew_requiresNew(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNew(user2);
        
        User2 user3=new User2();
        user3.setName("王五");
        user2Service.addRequiresNew(user3);
        throw new RuntimeException();
    }
3.4.2.3.2.总结

在这里插入图片描述

3.4.2.4.场景验证4:外围方法开启事务,内部方法抛出异常
3.4.2.4.1.Code
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_required_requiresNew_requiresNew_exception(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNew(user2);
        
        User2 user3=new User2();
        user3.setName("王五");
        user2Service.addRequiresNewException(user3);
    }
3.4.2.4.2.总结

在这里插入图片描述

3.4.2.5.场景验证5:外围方法开启事务,内部方法抛出异常
3.4.2.5.1.Code
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_required_requiresNew_requiresNew_exception_try(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNew(user2);
        User2 user3=new User2();
        user3.setName("王五");
        try {
            user2Service.addRequiresNewException(user3);
        } catch (Exception e) {
            System.out.println("回滚");
        }
    }
3.4.2.5.3.总结

在这里插入图片描述

3.4.2.6.结论
1.结论:通过这两个方法我们证明了在外围方法未开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,
  且开启的事务相互独立,互不干扰。
2.结论:在外围方法开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法依然会单独开启独立事务,且与外部方法事务也独立,
  内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。  

3.4.3.PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按 REQUIRED 属性执行。

3.4.3.1.原始数据:User1ServiceImpl和User2ServiceImpl

User1ServiceImpl

@Service
public class User1ServiceImpl implements User1Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addNested(User1 user){
        user1Mapper.insert(user);
    }
}

User2ServiceImpl

@Service
public class User2ServiceImpl implements User2Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addNested(User2 user){
        user2Mapper.insert(user);
    }
    
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addNestedException(User2 user){
        user2Mapper.insert(user);
        throw new RuntimeException();
    }
}
3.4.3.2.场景验证1:外围方法不开启事务,外围方法抛出异常
3.4.3.2.1.Code
    @Override
    public void notransaction_exception_nested_nested(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addNested(user2);
        throw new RuntimeException();
    }
3.4.3.2.2.总结

在这里插入图片描述

3.4.3.3.场景验证2:外围方法不开启事务,内部方法抛出异常
3.4.3.3.1.Code
    @Override
    public void notransaction_nested_nested_exception(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addNestedException(user2);
    }
3.4.3.3.2.总结

在这里插入图片描述

3.4.3.4.场景验证3:外围方法开启事务,外部方法抛出异常
3.4.3.4.1.Code
    @Transactional
    @Override
    public void transaction_exception_nested_nested(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addNested(user2);
        throw new RuntimeException();
    }
3.4.3.4.2.总结

在这里插入图片描述

3.4.3.5.场景验证4:外围方法开启事务,内部方法抛出异常
3.4.3.5.1.Code
    @Transactional
    @Override
    public void transaction_nested_nested_exception(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addNestedException(user2);
    }
3.4.3.5.2.总结

在这里插入图片描述

3.4.3.6.场景验证5:外围方法开启事务,内部方法抛出异常
3.4.3.6.1.Code
    @Transactional
    @Override
    public void transaction_nested_nested_exception_try(){
        User1 user1=new User1();
        user1.setName("张三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        try {
            user2Service.addNestedException(user2);
        } catch (Exception e) {
            System.out.println("方法回滚");
        }
    }
3.4.3.6.2.总结

在这里插入图片描述

3.4.3.7.结论
1.结论:通过这两个方法我们证明了在外围方法未开启事务的情况下Propagation.NESTED和Propagation.REQUIRED作用相同,
  修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干扰。
2.结论:以上试验结果我们证明在外围方法开启事务的情况下Propagation.NESTED修饰的内部方法属于外部事务的子事务,外围主事务回滚,
  子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务

3.4.4.PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

3.4.5.PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。

3.4.6.PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。

3.4.7.PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事 务,就把当前事务挂起。

3.5.事务传播机制配置

1.上面我们的样例都是通过java 硬编码的方式去配置事物的传播机制
2.这里我们通过配置文件的形式去指定事物的传播机制
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
						http://www.springframework.org/schema/tx 
						http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
						http://www.springframework.org/schema/aop 
						http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	<aop:aspectj-autoproxy proxy-target-class="true"/>
	
	<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="add*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
			<tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
			<tx:method name="edit*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
			<tx:method name="login" propagation="NOT_SUPPORTED"/>
			<tx:method name="query*" read-only="true"/>
		</tx:attributes>
	</tx:advice>

	<aop:config>
		<aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPointcut"/>
        <aop:aspect ref="dataSource">
            <aop:pointcut id="transactionPointcut" expression="execution(public * com.gaoxinfu..*.service..*Service.*(..))" />
        </aop:aspect>
    </aop:config>
	
</beans>

4.数据库的隔离级别

https://blog.csdn.net/u014636209/article/details/104104413
在这里插入图片描述

5.Spring的隔离级别

5.1.Spring的隔离级别类型

在这里插入图片描述

5.2.Spring的隔离级别使用样例

@Service
public class EmpServiceImpl implements EmpService {


	@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
	@Override
	public Long insert(Emp emp) {
		return null;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东山富哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值