@Transactional 涉及到兩個方面,一個是數據的持久化,第二個是數據庫的事務。關於持久化以及事務不做贅述。
在持久化中涉及到了實體管理器EntityManager類,該類通過@PersistenceContext進行註解,標識只注入一次實體管理器,但是因爲EntityManager是一個interface,所以它的注入是通過感知上下文內容進行注入的,因此是存在的問題的,所以需要進行一層代理,這層代理一般是用SharedEntityManagerInvocationHandler。
@Transactional的具體工作原理可從以下三個方面進行把握,EntityManager的代理,Transactional層面,Transactional管理器層面。
Transactional層面:它的執行包含執行前的決策,和執行後的處理,其中執行前是通過Transactional管理器決定如何進行的,這一步主要是決定新的事務怎麼處理。執行後是看結果是否進行commit或者進行roll back。
Transactional管理器層面:決定是否創建一個新的事務,是否創建一個新的實力管理器。如果決定要創建一個新的事務,那麼需要進行以下操作。創建一個新的事務,並且將這個新事務與當前已有的事務進行綁定,然後從數據庫連接池中拿取一個線程,並將該線程與當前事務進行綁定。
這裏需要注意的是如何決定是否創建一個新的事務,那麼就要從事務配置的傳播行爲TransactionDefinition說起:
(這一部分參考自https://www.cnblogs.com/yepei/p/4716112.html)
- Spring的默認是PROPAGATION_REQUIRED。如果當前存在事務就加入該事務,如果沒有就創建一個。
- PROPAGATION_REQUIRES_NEW。創建一個新的事務,如果當前存在事務,則把當前事務掛起。
- PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
- PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
- PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。
- PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
- PROPAGATION_NESTED:如果當前存在事務,則創建一個事務作爲當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價於TransactionDefinition.PROPAGATION_REQUIRED。
EntityManager代理層面 通過代理喚醒EntityManager