使用@Transactional(propagation = Propagation.SUPPORTS)和不加@Transactional 有什么區別?


Spring 的事務傳播機制中 Propagation.SUPPORTS 級別的意義是,如果當前環境有事務,就加入到當前事務;如果沒有事務,就以非事務的方式執行。從這個說明來看,使用這個級別和不加@Transaction注解也沒什么不一樣,找 API 看一下,枚舉 Propagation 的 SUPPORTS 項如下:

Support a current transaction, execute non-transactionally if none exists. Analogous to EJB transaction attribute of the same name.

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 Also:AbstractPlatformTransactionManager.setTransactionSynchronization(int)

除了意義的說明,文檔中還有一個 Note: 對於設置了 transaction synchronization 的事務管理器,兩種方式有微小的不同,即使用@Transactional(propagation = Propagation.SUPPORTS) 方式會定義一個事務作用域,等等… 但是還是沒理解有什么用,繼續看一下See 指向的地方

/**
 * Set when this transaction manager should activate the thread-bound
 * transaction synchronization support. Default is "always".
 * <p>Note that transaction synchronization isn't supported for
 * multiple concurrent transactions by different transaction managers.
 * Only one transaction manager is allowed to activate it at any time.
 * @see #SYNCHRONIZATION_ALWAYS
 * @see #SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
 * @see #SYNCHRONIZATION_NEVER
 * @see TransactionSynchronizationManager
 * @see TransactionSynchronization
 */
public final void setTransactionSynchronization(int transactionSynchronization) {
   this.transactionSynchronization = transactionSynchronization;
}

也沒看出什么,按照See的指示,去看 TransactionSynchronization

  1 package org.springframework.transaction.support;
  2 
  3 import java.io.Flushable;
  4 
  5 /**
  6  * Interface for transaction synchronization callbacks.
  7  * Supported by AbstractPlatformTransactionManager.
  8  *
  9  * <p>TransactionSynchronization implementations can implement the Ordered interface
 10  * to influence their execution order. A synchronization that does not implement the
 11  * Ordered interface is appended to the end of the synchronization chain.
 12  *
 13  * <p>System synchronizations performed by Spring itself use specific order values,
 14  * allowing for fine-grained interaction with their execution order (if necessary).
 15  *
 16  * @author Juergen Hoeller
 17  * @since 02.06.2003
 18  * @see TransactionSynchronizationManager
 19  * @see AbstractPlatformTransactionManager
 20  * @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
 21  */
 22 public interface TransactionSynchronization extends Flushable {
 23 
 24    /** Completion status in case of proper commit */
 25    int STATUS_COMMITTED = 0;
 26 
 27    /** Completion status in case of proper rollback */
 28    int STATUS_ROLLED_BACK = 1;
 29 
 30    /** Completion status in case of heuristic mixed completion or system errors */
 31    int STATUS_UNKNOWN = 2;
 32 
 33 
 34    /**
 35     * Suspend this synchronization.
 36     * Supposed to unbind resources from TransactionSynchronizationManager if managing any.
 37     * @see TransactionSynchronizationManager#unbindResource
 38     */
 39    void suspend();
 40 
 41    /**
 42     * Resume this synchronization.
 43     * Supposed to rebind resources to TransactionSynchronizationManager if managing any.
 44     * @see TransactionSynchronizationManager#bindResource
 45     */
 46    void resume();
 47 
 48    /**
 49     * Flush the underlying session to the datastore, if applicable:
 50     * for example, a Hibernate/JPA session.
 51     * @see org.springframework.transaction.TransactionStatus#flush()
 52     */
 53    @Override
 54    void flush();
 55 
 56    /**
 57     * Invoked before transaction commit (before "beforeCompletion").
 58     * Can e.g. flush transactional O/R Mapping sessions to the database.
 59     * <p>This callback does <i>not</i> mean that the transaction will actually be committed.
 60     * A rollback decision can still occur after this method has been called. This callback
 61     * is rather meant to perform work that's only relevant if a commit still has a chance
 62     * to happen, such as flushing SQL statements to the database.
 63     * <p>Note that exceptions will get propagated to the commit caller and cause a
 64     * rollback of the transaction.
 65     * @param readOnly whether the transaction is defined as read-only transaction
 66     * @throws RuntimeException in case of errors; will be <b>propagated to the caller</b>
 67     * (note: do not throw TransactionException subclasses here!)
 68     * @see #beforeCompletion
 69     */
 70    void beforeCommit(boolean readOnly);
 71 
 72    /**
 73     * Invoked before transaction commit/rollback.
 74     * Can perform resource cleanup <i>before</i> transaction completion.
 75     * <p>This method will be invoked after {@code beforeCommit}, even when
 76     * {@code beforeCommit} threw an exception. This callback allows for
 77     * closing resources before transaction completion, for any outcome.
 78     * @throws RuntimeException in case of errors; will be <b>logged but not propagated</b>
 79     * (note: do not throw TransactionException subclasses here!)
 80     * @see #beforeCommit
 81     * @see #afterCompletion
 82     */
 83    void beforeCompletion();
 84 
 85    /**
 86     * Invoked after transaction commit. Can perform further operations right
 87     * <i>after</i> the main transaction has <i>successfully</i> committed.
 88     * <p>Can e.g. commit further operations that are supposed to follow on a successful
 89     * commit of the main transaction, like confirmation messages or emails.
 90     * <p><b>NOTE:</b> The transaction will have been committed already, but the
 91     * transactional resources might still be active and accessible. As a consequence,
 92     * any data access code triggered at this point will still "participate" in the
 93     * original transaction, allowing to perform some cleanup (with no commit following
 94     * anymore!), unless it explicitly declares that it needs to run in a separate
 95     * transaction. Hence: <b>Use {@code PROPAGATION_REQUIRES_NEW} for any
 96     * transactional operation that is called from here.</b>
 97     * @throws RuntimeException in case of errors; will be <b>propagated to the caller</b>
 98     * (note: do not throw TransactionException subclasses here!)
 99     */
100    void afterCommit();
101 
102    /**
103     * Invoked after transaction commit/rollback.
104     * Can perform resource cleanup <i>after</i> transaction completion.
105     * <p><b>NOTE:</b> The transaction will have been committed or rolled back already,
106     * but the transactional resources might still be active and accessible. As a
107     * consequence, any data access code triggered at this point will still "participate"
108     * in the original transaction, allowing to perform some cleanup (with no commit
109     * following anymore!), unless it explicitly declares that it needs to run in a
110     * separate transaction. Hence: <b>Use {@code PROPAGATION_REQUIRES_NEW}
111     * for any transactional operation that is called from here.</b>
112     * @param status completion status according to the {@code STATUS_*} constants
113     * @throws RuntimeException in case of errors; will be <b>logged but not propagated</b>
114     * (note: do not throw TransactionException subclasses here!)
115     * @see #STATUS_COMMITTED
116     * @see #STATUS_ROLLED_BACK
117     * @see #STATUS_UNKNOWN
118     * @see #beforeCompletion
119     */
120    void afterCompletion(int status);
121 
122 }

從這看出點意思, spring 框架執行事務的過程中可以執行回調。而 AbstractPlatformTransactionManager.setTransactionSynchronization(int)方法就是控制是否可以執行的開關。
所以,使用 Propagation.SUPPORTS 方式 和 不使用 @Transaction 注解有兩點區別:

    1. 前者的方法可以獲取和當前事務環境一致的 Connection 或 Session,而后者肯定是新的;
    2. 前者可以在掛起事務、恢復事務的時侯執行回調方法,而后者做不到。

暫時先介紹到這,區別還有很多,但是希望你至少先了解這兩點區別!

另外,如果沒有加@Transaction,輸出台會有“Closing non transactional SqlSession”提示

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM