Spring 事务分析总结

基于 Spring事务分析总结 - JavaGuide 的总结

[TOC]

Spring 事务分析总结

事务的概念

什么是事务:

事务是由一组SQL语句组成的逻辑执行单元,这些语句要么全部执行,要么全部不执行。

事务的四大特性(ACID):

* 原子性
* 一致性
* 隔离性
* 持久性

隔离级别:

* 读未提交(脏读、不可重复读、幻读)
* 读已提交(不可重复读、幻读)
* 可重复读(幻读)
* 串行化

MySQL 如何保证原子性:

回滚日志(undo log)

MySQL 如何保证持久性:

重做日志(redo log)

Spring 对事务的支持

Spring 支持的两种事务管理的方式

Spring 支持两种事务管理的方式:

* 声明式事务
* 编程式事务

编程式事务

通过 TransactionManagerTransactionTemplate 手动管理事务:

@Autowired
private PlatformTransactionManager transactionManager;

public void testTransactionManager(){
    TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
    try {
        // 业务代码
        transactionManager.commit(transaction);
    }catch (Exception e){
        // 回滚
        transactionManager.rollback(transaction);
    }
}
@Autowired
TransactionTemplate transactionTemplate;

public void testTransactionTemplate(){
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            try {
                // 业务代码
            }catch (Exception e){
                // 回滚
                status.setRollbackOnly();
            }
        }
    });
}

声明式事务

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
public void testTransaction(){
    // 业务代码
}

事务管理接口介绍

在Spring 框架中,与事务管理相关的三个重要接口:

  • PlatformTransactionManager:为各平台的事务管理提供了抽象的接口
  • TransactionDefinition:事务定义(隔离级别、传播行为、超时、只读、回滚规则)
  • TransactionStatus:事务状态(是否回滚、是否完成)

Spring 对事务管理的设计采用了 适配器模式

1. Spring 定义了事务管理器的抽象接口 PlatformTransactionManager
2. Spring 为各平台提供了事务管理器的实现:DataSourceTransactionManager, HibernateTransactionManager, JpaTransactionManager
3. 各平台提供了事务管理的具体实现

Spring 通过事务管理器使各平台的事务管理实现适配 PlatformTransactionManager,从对事务管理提供了一致的编程模型

PlatformTransactionManager 接口

PlatformTransactionManager 接口:

package org.springframework.transaction;

import org.springframework.lang.Nullable;

/**
 * This is the central interface in Spring's imperative transaction infrastructure.
 * Applications can use this directly, but it is not primarily meant as an API:
 * Typically, applications will work with either TransactionTemplate or
 * declarative transaction demarcation through AOP.
 *
 * <p>For implementors, it is recommended to derive from the provided
 * {@link org.springframework.transaction.support.AbstractPlatformTransactionManager}
 * class, which pre-implements the defined propagation behavior and takes care
 * of transaction synchronization handling. Subclasses have to implement
 * template methods for specific states of the underlying transaction,
 * for example: begin, suspend, resume, commit.
 *
 * <p>The default implementations of this strategy interface are
 * {@link org.springframework.transaction.jta.JtaTransactionManager} and
 * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager},
 * which can serve as an implementation guide for other transaction strategies.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 16.05.2003
 * @see org.springframework.transaction.support.TransactionTemplate
 * @see org.springframework.transaction.interceptor.TransactionInterceptor
 * @see org.springframework.transaction.ReactiveTransactionManager
 */
public interface PlatformTransactionManager extends TransactionManager {

    /**
     * Return a currently active transaction or create a new one, according to
     * the specified propagation behavior.
     * <p>Note that parameters like isolation level or timeout will only be applied
     * to new transactions, and thus be ignored when participating in active ones.
     * <p>Furthermore, not all transaction definition settings will be supported
     * by every transaction manager: A proper transaction manager implementation
     * should throw an exception when unsupported settings are encountered.
     * <p>An exception to the above rule is the read-only flag, which should be
     * ignored if no explicit read-only mode is supported. Essentially, the
     * read-only flag is just a hint for potential optimization.
     * @param definition the TransactionDefinition instance (can be {@code null} for defaults),
     * describing propagation behavior, isolation level, timeout etc.
     * @return transaction status object representing the new or current transaction
     * @throws TransactionException in case of lookup, creation, or system errors
     * @throws IllegalTransactionStateException if the given transaction definition
     * cannot be executed (for example, if a currently active transaction is in
     * conflict with the specified propagation behavior)
     * @see TransactionDefinition#getPropagationBehavior
     * @see TransactionDefinition#getIsolationLevel
     * @see TransactionDefinition#getTimeout
     * @see TransactionDefinition#isReadOnly
     */
    TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
            throws TransactionException;

    /**
     * Commit the given transaction, with regard to its status. If the transaction
     * has been marked rollback-only programmatically, perform a rollback.
     * <p>If the transaction wasn't a new one, omit the commit for proper
     * participation in the surrounding transaction. If a previous transaction
     * has been suspended to be able to create a new one, resume the previous
     * transaction after committing the new one.
     * <p>Note that when the commit call completes, no matter if normally or
     * throwing an exception, the transaction must be fully completed and
     * cleaned up. No rollback call should be expected in such a case.
     * <p>If this method throws an exception other than a TransactionException,
     * then some before-commit error caused the commit attempt to fail. For
     * example, an O/R Mapping tool might have tried to flush changes to the
     * database right before commit, with the resulting DataAccessException
     * causing the transaction to fail. The original exception will be
     * propagated to the caller of this commit method in such a case.
     * @param status object returned by the {@code getTransaction} method
     * @throws UnexpectedRollbackException in case of an unexpected rollback
     * that the transaction coordinator initiated
     * @throws HeuristicCompletionException in case of a transaction failure
     * caused by a heuristic decision on the side of the transaction coordinator
     * @throws TransactionSystemException in case of commit or system errors
     * (typically caused by fundamental resource failures)
     * @throws IllegalTransactionStateException if the given transaction
     * is already completed (that is, committed or rolled back)
     * @see TransactionStatus#setRollbackOnly
     */
    void commit(TransactionStatus status) throws TransactionException;

    /**
     * Perform a rollback of the given transaction.
     * <p>If the transaction wasn't a new one, just set it rollback-only for proper
     * participation in the surrounding transaction. If a previous transaction
     * has been suspended to be able to create a new one, resume the previous
     * transaction after rolling back the new one.
     * <p><b>Do not call rollback on a transaction if commit threw an exception.</b>
     * The transaction will already have been completed and cleaned up when commit
     * returns, even in case of a commit exception. Consequently, a rollback call
     * after commit failure will lead to an IllegalTransactionStateException.
     * @param status object returned by the {@code getTransaction} method
     * @throws TransactionSystemException in case of rollback or system errors
     * (typically caused by fundamental resource failures)
     * @throws IllegalTransactionStateException if the given transaction
     * is already completed (that is, committed or rolled back)
     */
    void rollback(TransactionStatus status) throws TransactionException;

}

TransactionDefinition 接口

TransactionDefinition 定义了事务属性:隔离级别、传播行为、只读、超时、回滚规则

package org.springframework.transaction;

import org.springframework.lang.Nullable;

/**
 * Interface that defines Spring-compliant transaction properties.
 */
public interface TransactionDefinition {

   /**
    * Support a current transaction; create a new one if none exists.
    */
   int PROPAGATION_REQUIRED = 0;

   /**
    * Support a current transaction; execute non-transactionally if none exists.
    */
   int PROPAGATION_SUPPORTS = 1;

   /**
    * Support a current transaction; throw an exception if no current transaction exists.
    */
   int PROPAGATION_MANDATORY = 2;

   /**
    * Create a new transaction, suspending the current transaction if one exists.
    */
   int PROPAGATION_REQUIRES_NEW = 3;

   /**
    * Do not support a current transaction; rather always execute non-transactionally.
    */
   int PROPAGATION_NOT_SUPPORTED = 4;

   /**
    * Do not support a current transaction; throw an exception if a current transaction
    * exists.
    */
   int PROPAGATION_NEVER = 5;

   /**
    * Execute within a nested transaction if a current transaction exists,
    */
   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 = 1;  // same as java.sql.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 = 2;  // same as java.sql.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 = 4;  // same as java.sql.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 = 8;  // same as java.sql.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}.
    * <p>The default is {@link #PROPAGATION_REQUIRED}.
    * @return the propagation behavior
    * @see #PROPAGATION_REQUIRED
    * @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()
    */
   default int getPropagationBehavior() {
      return PROPAGATION_REQUIRED;
   }

   /**
    * Return the isolation level.
    * <p>Must return one of the {@code ISOLATION_XXX} constants defined on
    * {@link TransactionDefinition this interface}. Those constants are designed
    * to match the values of the same constants on {@link java.sql.Connection}.
    * <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
    * {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
    * transactions. Consider switching the "validateExistingTransactions" flag to
    * "true" on your transaction manager if you'd like isolation level declarations
    * to get rejected when participating in an existing transaction with a different
    * isolation level.
    * <p>The default is {@link #ISOLATION_DEFAULT}. 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
    * @see #ISOLATION_DEFAULT
    * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setValidateExistingTransaction
    */
   default int getIsolationLevel() {
      return ISOLATION_DEFAULT;
   }

   /**
    * Return the transaction timeout.
    * <p>Must return a number of seconds, or {@link #TIMEOUT_DEFAULT}.
    * <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
    * {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
    * transactions.
    * <p>Note that a transaction manager that does not support timeouts will throw
    * an exception when given any other timeout than {@link #TIMEOUT_DEFAULT}.
    * <p>The default is {@link #TIMEOUT_DEFAULT}.
    * @return the transaction timeout
    */
   default int getTimeout() {
      return TIMEOUT_DEFAULT;
   }

   /**
    * 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
    * ({@code false} by default)
    * @see org.springframework.transaction.support.TransactionSynchronization#beforeCommit(boolean)
    * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
    */
   default boolean isReadOnly() {
      return false;
   }

   /**
    * 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 ({@code null} by default}
    * @see org.springframework.transaction.interceptor.TransactionAspectSupport
    * @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionName()
    */
   @Nullable
   default String getName() {
      return null;
   }


   // Static builder methods

   /**
    * Return an unmodifiable {@code TransactionDefinition} with defaults.
    * <p>For customization purposes, use the modifiable
    * {@link org.springframework.transaction.support.DefaultTransactionDefinition}
    * instead.
    * @since 5.2
    */
   static TransactionDefinition withDefaults() {
      return StaticTransactionDefinition.INSTANCE;
   }

}

TransactionStatus 接口

package org.springframework.transaction;

import java.io.Flushable;

/**
 * Representation of the status of a transaction.
 *
 * <p>Transactional code can use this to retrieve status information,
 * and to programmatically request a rollback (instead of throwing
 * an exception that causes an implicit rollback).
 *
 * <p>Includes the {@link SavepointManager} interface to provide access
 * to savepoint management facilities. Note that savepoint management
 * is only available if supported by the underlying transaction manager.
 *
 * @author Juergen Hoeller
 * @since 27.03.2003
 * @see #setRollbackOnly()
 * @see PlatformTransactionManager#getTransaction
 * @see org.springframework.transaction.support.TransactionCallback#doInTransaction
 * @see org.springframework.transaction.interceptor.TransactionInterceptor#currentTransactionStatus()
 */
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

   /**
    * Return whether this transaction internally carries a savepoint,
    * that is, has been created as nested transaction based on a savepoint.
    * <p>This method is mainly here for diagnostic purposes, alongside
    * {@link #isNewTransaction()}. For programmatic handling of custom
    * savepoints, use the operations provided by {@link SavepointManager}.
    * @see #isNewTransaction()
    * @see #createSavepoint()
    * @see #rollbackToSavepoint(Object)
    * @see #releaseSavepoint(Object)
    */
   boolean hasSavepoint();

   /**
    * Flush the underlying session to the datastore, if applicable:
    * for example, all affected Hibernate/JPA sessions.
    * <p>This is effectively just a hint and may be a no-op if the underlying
    * transaction manager does not have a flush concept. A flush signal may
    * get applied to the primary resource or to transaction synchronizations,
    * depending on the underlying resource.
    */
   @Override
   void flush();

}
public interface TransactionExecution {
    boolean isNewTransaction();
    void setRollbackOnly();
    boolean isRollbackOnly();
    boolean isCompleted();
}
public interface SavepointManager {
   Object createSavepoint() throws TransactionException;
   void rollbackToSavepoint(Object savepoint) throws TransactionException;
   void releaseSavepoint(Object savepoint) throws TransactionException;
}

声明式事务注解介绍

声明式事务注解:

package org.springframework.transaction.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;
import org.springframework.transaction.TransactionDefinition;

/**
 * Describes a transaction attribute on an individual method or on a class.
 *
 * <p>At the class level, this annotation applies as a default to all methods of
 * the declaring class and its subclasses. Note that it does not apply to ancestor
 * classes up the class hierarchy; methods need to be locally redeclared in order
 * to participate in a subclass-level annotation.
 *
 * <p>This annotation type is generally directly comparable to Spring's
 * {@link org.springframework.transaction.interceptor.RuleBasedTransactionAttribute}
 * class, and in fact {@link AnnotationTransactionAttributeSource} will directly
 * convert the data to the latter class, so that Spring's transaction support code
 * does not have to know about annotations. If no rules are relevant to the exception,
 * it will be treated like
 * {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute}
 * (rolling back on {@link RuntimeException} and {@link Error} but not on checked
 * exceptions).
 *
 * <p>For specific information about the semantics of this annotation's attributes,
 * consult the {@link org.springframework.transaction.TransactionDefinition} and
 * {@link org.springframework.transaction.interceptor.TransactionAttribute} javadocs.
 *
 * @author Colin Sampaleanu
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @since 1.2
 * @see org.springframework.transaction.interceptor.TransactionAttribute
 * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute
 * @see org.springframework.transaction.interceptor.RuleBasedTransactionAttribute
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {

   /**
    * Alias for {@link #transactionManager}.
    * @see #transactionManager
    */
   @AliasFor("transactionManager")
   String value() default "";

   /**
    * A <em>qualifier</em> value for the specified transaction.
    * <p>May be used to determine the target transaction manager, matching the
    * qualifier value (or the bean name) of a specific
    * {@link org.springframework.transaction.TransactionManager TransactionManager}
    * bean definition.
    * @since 4.2
    * @see #value
    * @see org.springframework.transaction.PlatformTransactionManager
    * @see org.springframework.transaction.ReactiveTransactionManager
    */
   @AliasFor("value")
   String transactionManager() default "";

   /**
    * The transaction propagation type.
    * <p>Defaults to {@link Propagation#REQUIRED}.
    * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior()
    */
   Propagation propagation() default Propagation.REQUIRED;

   /**
    * The transaction isolation level.
    * <p>Defaults to {@link Isolation#DEFAULT}.
    * <p>Exclusively designed for use with {@link Propagation#REQUIRED} or
    * {@link Propagation#REQUIRES_NEW} since it only applies to newly started
    * transactions. Consider switching the "validateExistingTransactions" flag to
    * "true" on your transaction manager if you'd like isolation level declarations
    * to get rejected when participating in an existing transaction with a different
    * isolation level.
    * @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel()
    * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setValidateExistingTransaction
    */
   Isolation isolation() default Isolation.DEFAULT;

   /**
    * The timeout for this transaction (in seconds).
    * <p>Defaults to the default timeout of the underlying transaction system.
    * <p>Exclusively designed for use with {@link Propagation#REQUIRED} or
    * {@link Propagation#REQUIRES_NEW} since it only applies to newly started
    * transactions.
    * @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout()
    */
   int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

   /**
    * A boolean flag that can be set to {@code true} if the transaction is
    * effectively read-only, allowing for corresponding optimizations at runtime.
    * <p>Defaults to {@code false}.
    * <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
    * but rather silently ignore the hint.
    * @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly()
    * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
    */
   boolean readOnly() default false;

   /**
    * Defines zero (0) or more exception {@link Class classes}, which must be
    * subclasses of {@link Throwable}, indicating which exception types must cause
    * a transaction rollback.
    * <p>By default, a transaction will be rolling back on {@link RuntimeException}
    * and {@link Error} but not on checked exceptions (business exceptions). See
    * {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)}
    * for a detailed explanation.
    * <p>This is the preferred way to construct a rollback rule (in contrast to
    * {@link #rollbackForClassName}), matching the exception class and its subclasses.
    * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}.
    * @see #rollbackForClassName
    * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
    */
   Class<? extends Throwable>[] rollbackFor() default {};

   /**
    * Defines zero (0) or more exception names (for exceptions which must be a
    * subclass of {@link Throwable}), indicating which exception types must cause
    * a transaction rollback.
    * <p>This can be a substring of a fully qualified class name, with no wildcard
    * support at present. For example, a value of {@code "ServletException"} would
    * match {@code javax.servlet.ServletException} and its subclasses.
    * <p><b>NB:</b> Consider carefully how specific the pattern is and whether
    * to include package information (which isn't mandatory). For example,
    * {@code "Exception"} will match nearly anything and will probably hide other
    * rules. {@code "java.lang.Exception"} would be correct if {@code "Exception"}
    * were meant to define a rule for all checked exceptions. With more unusual
    * {@link Exception} names such as {@code "BaseBusinessException"} there is no
    * need to use a FQN.
    * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String exceptionName)}.
    * @see #rollbackFor
    * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
    */
   String[] rollbackForClassName() default {};

   /**
    * Defines zero (0) or more exception {@link Class Classes}, which must be
    * subclasses of {@link Throwable}, indicating which exception types must
    * <b>not</b> cause a transaction rollback.
    * <p>This is the preferred way to construct a rollback rule (in contrast
    * to {@link #noRollbackForClassName}), matching the exception class and
    * its subclasses.
    * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)}.
    * @see #noRollbackForClassName
    * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
    */
   Class<? extends Throwable>[] noRollbackFor() default {};

   /**
    * Defines zero (0) or more exception names (for exceptions which must be a
    * subclass of {@link Throwable}) indicating which exception types must <b>not</b>
    * cause a transaction rollback.
    * <p>See the description of {@link #rollbackForClassName} for further
    * information on how the specified names are treated.
    * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String exceptionName)}.
    * @see #noRollbackFor
    * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
    */
   String[] noRollbackForClassName() default {};

}

传播行为的枚举类:

package org.springframework.transaction.annotation;

import org.springframework.transaction.TransactionDefinition;

/**
 * Enumeration that represents transaction propagation behaviors for use
 * with the {@link Transactional} annotation, corresponding to the
 * {@link TransactionDefinition} interface.
 *
 * @author Colin Sampaleanu
 * @author Juergen Hoeller
 * @since 1.2
 */
public enum Propagation {

   REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
   SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
   MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
   REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
   NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
   NEVER(TransactionDefinition.PROPAGATION_NEVER),
   NESTED(TransactionDefinition.PROPAGATION_NESTED);

   private final int value;

   Propagation(int value) {
      this.value = value;
   }

   public int value() {
      return this.value;
   }

}

隔离级别的枚举类:

package org.springframework.transaction.annotation;

import org.springframework.transaction.TransactionDefinition;

/**
 * Enumeration that represents transaction isolation levels for use
 * with the {@link Transactional} annotation, corresponding to the
 * {@link TransactionDefinition} interface.
 *
 * @author Colin Sampaleanu
 * @author Juergen Hoeller
 * @since 1.2
 */
public enum Isolation {

   DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
   READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
   READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
   REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
   SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);

   private final int value;


   Isolation(int value) {
      this.value = value;
   }

   public int value() {
      return this.value;
   }

}

事务属性详解

Spring事务传播行为详解

嵌套事务 - 百度百科

事务传播行为

常用的事务传播行为有:

PROPAGATION_REQUIRED(默认)
PROPAGATION_REQUIRES_NEW
PROPAGATION_NESTED

事务传播行为是为了解决业务层方法之间相互调用的事务问题。

传播行为 描述 回滚
PROPAGATION_REQUIRED 如果外部方法没有开启事务,则创建一个新事务;<br />如果外部方法有开启事务,则参与外部事务; 任何方法发生异常都会导致事务回滚
PROPAGATION_REQUIRES_NEW 如果外部方法开启事务,则挂起外部事务。并且总是创建新事务。 如果外部方法发生异常,只会回滚外部事务;<br />如果内部方法发生异常,则会回滚内部事务,如果外部方法未捕获异常,则会同时回滚外部事务;
PROPAGATION_NESTED 如果外部方法没有开启事务,则创建新事务;<br />如果外部方法开启事务,则内部事务作为外部事务的子事务; 嵌套事务:外部事务回滚时,子事务会跟着回滚;子事务可以独立的提交或回滚,而不影响外部事务。

事务隔离级别

并发异常:

更新异常:
* (回滚导致的)第一类丢失更新
* (提交导致的)第二类丢失更新
读取异常:
* 脏读(读取其他事务未提交的数据)
* 不可重复读(两次读取同一行数据却得到不同的值)
* 幻读(两次读取同一条件的数据却得到不同的结果集)

隔离级别:

隔离级别 解决的异常
读未提交 所有的读取异常都会出现
读已提交 不会出现脏读,会出现不可重复读、幻读
可重复读 不会出现脏读和不可重复读,会出现幻读
串行化 所有的读取异常都不会出现

实现机制:

悲观锁:
* 共享锁
* 排他锁
乐观锁

更新异常:

// 数据库实现了悲观锁,在更新数据时对数据加上排他锁,所以不会出现更新异常。
// 但要避免应用逻辑的更新异常
//
// 以下代码不是原子性的,所以会导致第二类丢失更新
public void UpdateException(){
    Data data = selectData();
    // process data
    updateData(data);
}

MySQL 的可重复读:

1. MySQL 默认隔离级别是可重复读
2. MySQL InnoDB 的可重复读通过临键锁解决了幻读问题

事务超时

事务被允许的最长执行时间,超过该时间将自动回滚。

只读事务

将多条查询语句放在一个事务中,保证整个查询的一致性。

回滚规则

在声明式注解有两个参数可以定义回滚规则:默认是遇到 ErrorRuntimeException 时回滚事务

/**
 * Defines zero (0) or more exception {@link Class classes}, which must be
 * subclasses of {@link Throwable}, indicating which exception types must cause
 * a transaction rollback.
 * <p>By default, a transaction will be rolling back on {@link RuntimeException}
 * and {@link Error} but not on checked exceptions (business exceptions). See
 * {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)}
 * for a detailed explanation.
 * <p>This is the preferred way to construct a rollback rule (in contrast to
 * {@link #rollbackForClassName}), matching the exception class and its subclasses.
 * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}.
 * @see #rollbackForClassName
 * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
 */
Class<? extends Throwable>[] rollbackFor() default {};


/**
 * Defines zero (0) or more exception {@link Class Classes}, which must be
 * subclasses of {@link Throwable}, indicating which exception types must
 * <b>not</b> cause a transaction rollback.
 * <p>This is the preferred way to construct a rollback rule (in contrast
 * to {@link #noRollbackForClassName}), matching the exception class and
 * its subclasses.
 * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)}.
 * @see #noRollbackForClassName
 * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
 */
Class<? extends Throwable>[] noRollbackFor() default {};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352