SpringBoot (15)---事務處理
SpringBoot 中的事務處理
前兩章節主要講解了在SpringBoot中關於對資料的操作,本章節將介紹如何進行事務處理。所有的資料訪問技術都離不開事務處理,否則將會造成資料不一致。事務是一系列的動作,一旦其中有一個動作出現錯誤,必須全部回滾,系統將事務中對資料庫的所有已完成的操作全部撤消,滾回到事務開始的狀態,避免出現由於資料不一致而導致的接下來一系列的錯誤。事務的出現是為了確保資料的完整性和一致性,在目前企業級應用開發中,事務管理是必不可少的。
1、SpringBoot事務機制
事務處理機制都會提供API來開啟事務、提交事務來完成資料操作,或者在發生錯誤的時候回滾資料,避免資料的不完整性、不一致性。
SpringBoot事務機制實質上就是Spring的事務機制,是採用統一的機制處理來自不同資料訪問技術的事務處理,提供了一個介面 PlatformTransactionManager,已經為不同資料訪問技術可以進行不同的實現,如下表。
資料訪問技術 | 實現類 |
JDBC | DataSourceTransactionManager |
JPA | JpaTransactionManager |
Hibernate | HibernateTransactionManager |
JDO | JdoTransactionManager |
分散式事務 | JtaTransactionManager |
涉及到介面關係如下:
介面PlatformTransactionManager原始碼如下:
-
/*
-
* Copyright 2002-2012 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 org.springframework.lang.Nullable;
-
/**
-
* This is the central interface in Spring's transaction infrastructure.
-
* Applications can use this directly, but it is not primarily meant as 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.interceptor.TransactionProxyFactoryBean
-
*/
-
public interface PlatformTransactionManager {
-
/**
-
* 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 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;
-
}
2、宣告式事務
建立在AOP之上的,其本質是對方法前後進行攔截,然後在目標方法開始之前建立或者加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。宣告式事務最大的優點就是不需要通過程式設計的方式管理事務,這樣就不需要在業務邏輯程式碼中摻雜事務管理的程式碼,只需在配置檔案中做相關的事務規則宣告(或通過基於@Transactional註解的方式),便可以將事務規則應用到業務邏輯中。
Spring支援宣告式事務,被註解的方法在被呼叫時,Spring開啟一個新的事務,當方法無異常結束後,Spring會提交這個事務。
-
@Transactional
-
public void insertUser(User user) {
-
//資料庫表的操作
-
……
-
}
注:
(1)@Transactional是來自org.springframework.transaction.annotation包的。
(2)@Transactional不僅可以註解在方法上,也可以註解在類上。當註解在類上時,意味著此類的所有public方法都是開啟事務的。如果類級別和方法級別同時使用了@Transactional註解,則使用在類級別的註解會過載方法級別的註解。
以下為註解@Transactional原始碼:
(為了縮小所佔篇數,故去掉註釋部分)
-
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;
-
@Target({ElementType.METHOD, ElementType.TYPE})
-
@Retention(RetentionPolicy.RUNTIME)
-
@Inherited
-
@Documented
-
public @interface Transactional {
-
@AliasFor("transactionManager")
-
String value() default "";
-
@AliasFor("value")
-
String transactionManager() default "";
-
Propagation propagation() default Propagation.REQUIRED;
-
Isolation isolation() default Isolation.DEFAULT;
-
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
-
boolean readOnly() default false;
-
Class<? extends Throwable>[] rollbackFor() default {};
-
String[] rollbackForClassName() default {};
-
Class<? extends Throwable>[] noRollbackFor() default {};
-
String[] noRollbackForClassName() default {};
-
}
屬性說明如下表:
屬性 | 型別 | 描述 |
---|---|---|
value | String | 可選的限定描述符,指定使用的事務管理器 |
propagation | enum: Propagation | 定義事務的生命週期,有REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED,詳細含義可查閱列舉類org.springframework.transaction.annotation.Propagation原始碼。 |
isolation | enum: Isolation | 可選的事務隔離級別設定,決定了事務的完整性 |
readOnly | boolean | 讀寫或只讀事務,預設讀寫 |
timeout | int (in seconds granularity) | 事務超時時間設定 |
rollbackFor | Class物件陣列,必須繼承自Throwable | 導致事務回滾的異常類陣列 |
rollbackForClassName | 類名陣列,必須繼承自Throwable | 導致事務回滾的異常類名字陣列 |
noRollbackFor | Class物件陣列,必須繼承自Throwable | 不會導致事務回滾的異常類陣列 |
noRollbackForClassName | 類名陣列,必須繼承自Throwable | 不會導致事務回滾的異常類名字陣列 |
在SpringBoot中,建議採用註解@Transactional進行事務的控制。