首頁  >  文章  >  Java  >  Spring中@Transactional用法詳細介紹

Spring中@Transactional用法詳細介紹

黄舟
黄舟原創
2017-03-07 10:31:202200瀏覽

這篇文章主要介紹了Spring中@Transactional用法詳細介紹的相關資料,需要的朋友可以參考下

Spring中@Transactional用法詳細介紹

引言: 在spring中@Transactional提供一種控制事務管理引言的快速手段,但很多人只是@Transactional簡單使用,並未深入了解,其各個配置項的使用方法,本文將深入講解各個配置項的使用。

1.  @Transactional的定義

    Spring中的@Transactional基於動態代理的機制,提供了一種透明的事務管理機制,方便快速解決在開發中碰到的問題。在現實中,實際的問題往往比我們預期的要複雜很多,這就要求對@Transactional有深入的了解,以來應對複雜問題。

   首先我們來看看@Transactional的程式碼定義:

@Target({ElementType.METHOD, ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Inherited 
@Documented 
public @interface Transactional { 
 
  /** 
   * A qualifier 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.PlatformTransactionManager} 
   * bean definition. 
   */ 
  String value() default ""; 
 
  /** 
   * The transaction propagation type. 
   * Defaults to {@link Propagation#REQUIRED}. 
   * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior() 
   */ 
  Propagation propagation() default Propagation.REQUIRED; 
 
  /** 
   * The transaction isolation level. 
   * Defaults to {@link Isolation#DEFAULT}. 
   * @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel() 
   */ 
  Isolation isolation() default Isolation.DEFAULT; 
 
  /** 
   * The timeout for this transaction. 
   * Defaults to the default timeout of the underlying transaction system. 
   * @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout() 
   */ 
  int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; 
 
  /** 
   * {@code true} if the transaction is read-only. 
   * 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. 
   * @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly() 
   */ 
  boolean readOnly() default false; 
 
  /** 
   * Defines zero (0) or more exception {@link Class classes}, which must be a 
   * subclass of {@link Throwable}, indicating which exception types must cause 
   * a transaction rollback. 
   * <p>This is the preferred way to construct a rollback rule, matching the 
   * exception class and subclasses. 
   * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)} 
   */ 
  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, with no wildcard support at present. 
   * A value of "ServletException" would match 
   * {@link javax.servlet.ServletException} and subclasses, for example. 
   * <p><b>NB: </b>Consider carefully how specific the pattern is, and whether 
   * to include package information (which isn&#39;t mandatory). For example, 
   * "Exception" will match nearly anything, and will probably hide other rules. 
   * "java.lang.Exception" would be correct if "Exception" was meant to define 
   * a rule for all checked exceptions. With more unusual {@link Exception} 
   * names such as "BaseBusinessException" there is no need to use a FQN. 
   * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String exceptionName)} 
   */ 
  String[] rollbackForClassName() default {}; 
 
  /** 
   * Defines zero (0) or more exception {@link Class Classes}, which must be a 
   * subclass 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, matching the 
   * exception class and subclasses. 
   * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)} 
   */ 
  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 more info on how 
   * the specified names are treated. 
   * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String exceptionName)} 
   */ 
  String[] noRollbackForClassName() default {}; 
 
}

  基於原始程式碼,我們可以發現在@Transactional,原來有這麼多的屬性可以進行配置,從而達到複雜應用控制的目的。具體各屬性的用法和作用,將在本文的後面逐一來講解和說明。

2.  使用@Transactional的Spring配置

     為了使用基於@Transactional的事務管理,需要在Spring中進行如下的配置:來源的物件實例,EntityManagerFactory是基於JPA使用的實體類別管理器:org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean。這些都是用來配置與資料庫的連接訊息,本質上,@Transactional使用了JDBC的事務來進行事務控制的。

    標籤的聲明,則是在Spring內部啟用@Transactional來進行事務管理,類似開關之類的聲明。

3.  @Transactional之value

    value這裡主要用來指定不同的事務管理器;主要用來滿足在同一個系統中,存在不同的事務管理器。例如在Spring中,聲明了兩種事務管理器txManager1, txManager2.

然後,用戶可以根據這個參數來根據需要指定特定的txManager.   那有同學會問什麼情況下會存在多個事務管理器的情況呢? 例如在一個系統中,需要存取多個資料來源或多個資料庫,則必然會配置多個事務管理器的。

4.   @Transactional之propagation

      Propagation支持7種不同的傳播機制:

  業務方法需要在一個事務中運行,如果方法運行時,已處在一個事務中,那麼就加入該事務,否則自己創建一個新的事務.這是spring預設的傳播行為.。 

 SUPPORTS:  

              


 MANDATORY:

              NEW


             業務方法總是會為自己發起一個新的事務,如果方法已運行在一個事務中,則原有事務被掛起,新的事務被創建,直到方法結束,新事務才結束,原先的事務才結束,原有事務被掛起,新的事務被創建,直到方法結束,新事務才結束,原先的事務才結束會恢復執行.


 NOT_SUPPORTED


           聲明方法、該事務,如果方法沒有關聯到一個事務,容器不會為它所開啟事務在方法呼叫結束後,原先的事務便會恢復執行.


NEVER:


          沒有關聯到事務,才正常執行.

 NESTED:

          如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动的事务,则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保证点.内部事务回滚不会对外部事务造成影响, 它只对DataSourceTransactionManager 事务管理器起效.

     其实大家最感到困惑的是REQUIRED_NEW和NESTED两种不同的传播机制,功能类似,都涉及到了事务嵌套的问题,那两者有何区别呢?该如何正确使用这两种模式呢?

        以下是摘自Spring的文档:

  PROPAGATION_REQUIRES_NEW : uses a completely independent transaction for
 each affected transaction scope. In that case, the underlying physical 
transactions are different and hence can commit or roll back independently, 
with an outer transaction not affected by an inner transaction&#39;s rollback status.

         内部的事务独立运行,在各自的作用域中,可以独立的回滚或者提交;而外部的事务将不受内部事务的回滚状态影响。   

 ROPAGATION_NESTED : uses a single physical transaction with multiple 
savepoints that it can roll back to. Such partial rollbacks allow an
 inner transaction scope to trigger a rollback for its scope, with the outer 
transaction being able to continue the physical transaction despite some operations 
having been rolled back. This setting is typically mapped onto JDBC savepoints, so will 
only work with JDBC resource transactions.

       NESTED的事务,基于单一的事务来管理,提供了多个保存点。这种多个保存点的机制允许内部事务的变更触发外部事务的回滚。而外部事务在混滚之后,仍能继续进行事务处理,即使部分操作已经被混滚。 由于这个设置基于JDBC的保存点,所以只能工作在JDBC的机制智商。

       由此可知, 两者都是事务嵌套,不同之处在于,内外事务之间是否存在彼此之间的影响;NESTED之间会受到影响,而产生部分回滚,而REQUIRED_NEW则是独立的。

 以上就是Spring中@Transactional用法详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn