Spring Data JPA 是 Spring 基於 ORM 框架、JPA 規范的基礎上封裝的一套 JPA 應用框架,可使開發者用極簡的代碼即可實現對數據的訪問和操作。它提供了包括增刪改查等在內的常用功能,且易於擴展。以下介紹JPA事務
1.事務基礎:
事務的基本概念:即訪問並可能更新數據庫中各種數據項的一個程序執行單元。
需要管理事務的執行,要么成功、要么失敗,一但失敗,所有操作將回滾到初始狀態,一但成功,則進行持久化。
事務特性ACID:原子性、一致性、隔離性(並發執行的事務不能相互干擾)、持久性(對數據庫的改變是永久性)
Spring Data JPA事務分為:JTA事務(分布式事務,多種數據庫)、RESOURCE_LOCAL事務(本地事務,數據庫級別,僅支持一種數據庫)
2.數據庫事務並發帶來的問題
臟讀:一句話表達事務讀取了其他並發事務未提交的數據
事務B讀取了事務A未提交的數據,事務B按未提交的數據進行執行並提交。而事務A又對數據進行修改后再提交。這樣事務B讀取的數據與事務A提交的數據不一致。
不可重復讀:同一個事務先后兩次或兩次以上讀取同一數據,結果不一樣。
事務C讀取了數據,事務還沒有提交。
事務D修改了數據,並提交事務。隨后,事務C再次讀取時,發現數據變了。
幻讀:跟不可重復讀類似,側重記錄的數量(行數),不可重復讀側重於數據的值。
3.事務的傳播特性:
FunctionA調用FunctionB
1. PROPAGATION_REQUIRED: 如果存在一個事務,則支持當前事務。如果沒有事務則開啟
2. PROPAGATION_SUPPORTS: 如果存在一個事務,支持當前事務。如果沒有事務,則非事務的執行
3. PROPAGATION_MANDATORY: 如果已經存在一個事務,支持當前事務。如果沒有一個活動的事務,則拋出異常。
4. PROPAGATION_REQUIRES_NEW: 總是開啟一個新的事務。如果一個事務已經存在,則將這個存在的事務掛起。
5. PROPAGATION_NOT_SUPPORTED: 總是非事務地執行,並掛起任何存在的事務。
6. PROPAGATION_NEVER: 總是非事務地執行,如果存在一個活動事務,則拋出異常
7. PROPAGATION_NESTED:如果一個活動的事務存在,則運行在一個嵌套的事務中. 如果沒有活動事務, 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執行
4.事務的隔離級別:
1. ISOLATION_DEFAULT: 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別.另外四個與JDBC的隔離級別相對應
2. ISOLATION_READ_UNCOMMITTED: 這是事務最低的隔離級別,它充許令外一個事務可以看到這個事務未提交的數據。這種隔離級別會產生臟讀,不可重復讀和幻像讀。
3. ISOLATION_READ_COMMITTED: 保證一個事務修改的數據提交后才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數據
4. ISOLATION_REPEATABLE_READ: 這種事務隔離級別可以防止臟讀,不可重復讀。但是可能出現幻像讀。它除了保證一個事務不能讀取另一個事務未提交的數據外,還保證了避免下面的情況產生(不可重復讀)。
5. ISOLATION_SERIALIZABLE 這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。除了防止臟讀,不可重復讀外,還避免了幻像讀。
通常使用數據庫的默認隔離級別即可,基本不需要進行設置
MYSQL: 默認為REPEATABLE_READ級別
SQLSERVER: 默認為READ_COMMITTED
5.配置事務
先在spring配置文件中引入<tx:>命名空間
5.1通過注解配置事務:
<!-- 事務管理器配置, Hibernate單數據源事務 --> <bean id="defaultTransactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 使用annotation定義事務 --> <tx:annotation-driven transaction-manager="defaultTransactionManager" proxy-target-class="true" />
配置完之后,就可通過@Transactional 注解的bean自動配置為聲明式事務支持 .
注意以下問題:
a.<tx:annotation-driven/>元素的出現開啟了事務行為,@Transactional 是元數據標記,只有在前者配置后,再使用@Transactional才能開啟事務
b.@Transactional 可以添加到Dao層或Servive層(具體的實現類)的 public 可見度的方法上,而不要使用在類所要實現的任何接口上。你當然可以在接口上使用 @Transactional 注解,但是這將只能當你設置了基於接口的代理時它才生效。因為注解是 不能繼承 的
5.2通過AOP配置事務:
<!--事務的 AOP 配置--> <!--advisor--> <tx:advice id="applicationAdvisor" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> <tx:method name="load*" propagation="REQUIRED" read-only="false" isolation="DEFAULT" rollback-for="UserNotFoundException,UserNotFound2Exception"/> <tx:method name="is*" propagation="REQUIRED" read-only="false"/> </tx:attributes> </tx:advice> <aop:config> <aop:advisor advice-ref="applicationAdvisor" pointcut="execution(* com.mm.*.service.impl.*.*(..))"/> </aop:config>