天天看點

Spring完整揭秘(九):Spring的事務管理

文章目錄

  • ​​認識事務​​
  • ​​Spring事務架構​​
  • ​​TransactionDefinition 接口:​​
  • ​​TransactionStatus 接口​​
  • ​​PlatformTransactionManager接口​​
  • ​​Spring 聲明式事務管理​​
  • ​​基于 @Transactional 的聲明式事務管理​​
  • ​​@Transactional聲明式事務的例子​​

認識事務

  • 以可控的方式對資料資源進行通路的一組操作稱為事務;在事務執行前後,資料資源所承載的系統狀态始終處于正确的狀态。
  • 事務特性(ACID)
  1. 原子性(Atomicity):事務包括的全部操作是一個整體,象原子一樣不可分割。這些操作要麼全部送出成功,但隻要其中一個操作失敗,則全部失敗。
  2. 一緻性(Consistency):保證事務開始和結束之間的中間狀态不會被其他事務看到。
  3. 隔離性(Isolation):适當的破壞一緻性來提升性能與并行度 。
  4. 持久性(Durability):每一次的事務送出後就會保證不會丢失。
  • 事務隔離性的從弱到強分别為
  1. Read Uncommitted(讀取未送出内容)
  2. Read Committed(讀取送出内容)
  3. Repeatable Read(可重讀)
  4. Serializable(可串行化)
  • 事務職離級别越 強,一緻性越好,并發性越差。

Spring事務架構

  • Spring的事務抽象包括3個主要接口:
  1. PlatformTransactionManager事務管理器。
  2. TransactionDefinition事務定義資訊(事務隔離級别、傳播行為、逾時、隻讀、復原規則)。
  3. TransactionStatus事務運作狀态。
Spring完整揭秘(九):Spring的事務管理
TransactionDefinition 接口:
  • 當事務方法被另一個事務方法調用時,必須指定事務應該如何傳播。例如:方法可能繼續在現有事務中運作,也可能開啟一個新事務,并在自己的事務中運作。Spring定義了七種傳播行為:
定義 說明
PROPAGATION_REQUIRED 如果目前沒有事務,就建立一個事務,如果已經存在一個事務,則加入到這個事務中。這是最常見的選擇。
PROPAGATION_SUPPORTS 支援目前事務,如果目前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY 表示該方法必須在事務中運作,如果目前事務不存在,則會抛出一個異常。
PROPAGATION_REQUIRED_NEW 表示目前方法必須運作在它自己的事務中。一個新的事務将被啟動。如果存在目前事務,在該方法執行期間,目前事務會被挂起。
PROPAGATION_NOT_SUPPORTED 表示該方法不應該運作在事務中。如果目前存在事務,就把目前事務挂起。
PROPAGATION_NEVER 表示目前方法不應該運作在事務上下文中。如果目前正有一個事務在運作,則會抛出異常。
PROPAGATION_NESTED 如果目前存在事務,則在嵌套事務内執行。如果目前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。
TransactionStatus 接口
  • 在事務處理過程中,我們可以使用TransactionStatus 接口進行如下工作:
  1. 查詢事務狀态;
  2. 通過setRollbackOnly方法标記目前事務以使其復原;
  3. 建立内部嵌套事務。
PlatformTransactionManager接口
  • Spring的事務抽象架構以PlatformTransactionManager作為頂層抽象接口,具體的實作交給不同的實作類,使用對象可以根據目前場景,選擇使用或者替換哪一個具體的實作類。
  • Spring完整揭秘(九):Spring的事務管理

Spring 聲明式事務管理

  • 随着SpringBoot的誕生與推廣,基于注解的聲明式事務管理已經得到了廣泛使用。聲明式事務管理是建立在 Spring AOP
基于 @Transactional 的聲明式事務管理
  1. 配置檔案開啟注解驅動,在相關的類和方法上通過注解@Transactional辨別。
  2. Spring 在啟動的時候會去解析生成相關的bean,這時候會檢視擁有相關注解的類和方法,并且為這些類和方法生成代理,并根據@Transaction的相關參數進行相關配置注入。
  3. 真正的資料庫層的事務送出和復原是通過binlog或者redo log實作的。
Spring完整揭秘(九):Spring的事務管理
  • @Transactional 注解的屬性資訊
屬性名 說明
name 當在配置檔案中有多個 TransactionManager , 可以用該屬性指定選擇哪個事務管理器。
propagation 事務的傳播行為,預設值為 REQUIRED。
isolation 事務的隔離度,預設值采用 DEFAULT。
timeout 事務的逾時時間,預設值為-1。如果超過該時間限制但事務還沒有完成,則自動復原事務。
read-only 指定事務是否為隻讀事務,預設值為 false;為了忽略那些不需要事務的方法,比如讀取資料,可以設定 read-only 為 true。
@Transactional聲明式事務的例子
/**
* 基于 @Transactional 的聲明式事務管理
*/
@Service
public class UserService {

    // Spring Data JPA
    @Autowired
    private UserRepository userRepository;
    // Mybatis
    @Autowired
    private UserMapper userMapper;
    // DAO
    @Autowired
    private UserDAOImpl userDAO;

    // 傳回所有的使用者
    @Transactional(readOnly = true,timeout = 20)
    public List<User> listUsers() {
        return (List<User>) userRepository.findAll();
    }

    // 儲存使用者
    @Transactional(rollbackFor = Exception.class)
    public User saveUser(User user) {
        userDAO.addUser(user);
        if (user.getName().contains("admin")) {
            throw new RuntimeException("名稱中不能含有admin");
        }
        return user;
    }

    // 删除使用者
    @Transactional
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }

    // 查找使用者
    @Transactional(readOnly = true)
    public User findUser(Long id) {
        return userRepository.findById(id).get();
    }

    // 根據名稱查找使用者--Mybatis
    @Transactional(readOnly = true)
    public List<User> searchUser(String name) {
        return userMapper.findByName(name);
    }
}