Spring AOP在Hibernate事務管理
事務管理是用來以確保數據庫中數據的完整性和一致性。Spring AOP技術允許開發者管理事務的聲明。
這裏有一個例子來說明如何使用Spring AOP 來管理 Hibernate 事務。整個工程的文件結構如下所示:
P.S 這裏很多Hibernate和Spring配置文件是隱藏的,只有一些重要的文件顯示,如果你想看全部文件,請在文章的結尾下載完整的項目代碼。
1.創建表
MySQL表的腳本,一個「product」表
CREATE TABLE `yiibai`.`product` (
`PRODUCT_ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`PRODUCT_CODE` varchar(20) NOT NULL,
`PRODUCT_DESC` varchar(255) NOT NULL,
PRIMARY KEY (`PRODUCT_ID`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `yiibai`.`product_qoh` (
`QOH_ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`PRODUCT_ID` bigint(20) unsigned NOT NULL,
`QTY` int(10) unsigned NOT NULL,
PRIMARY KEY (`QOH_ID`),
KEY `FK_product_qoh_product_id` (`PRODUCT_ID`),
CONSTRAINT `FK_product_qoh_product_id` FOREIGN KEY (`PRODUCT_ID`)
REFERENCES `product` (`PRODUCT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2.產品業務對象
在這個「productBo」實現save()方法將插入記錄到「product「通過「ProductDao」,並通過「productQohBo」類庫存量到「productQoh'表。
package com.yiibai.product.bo.impl;
import com.yiibai.product.bo.ProductBo;
import com.yiibai.product.bo.ProductQohBo;
import com.yiibai.product.dao.ProductDao;
import com.yiibai.product.model.Product;
import com.yiibai.product.model.ProductQoh;
public class ProductBoImpl implements ProductBo{
ProductDao productDao;
ProductQohBo productQohBo;
public void setProductDao(ProductDao productDao) {
this.productDao = productDao;
}
public void setProductQohBo(ProductQohBo productQohBo) {
this.productQohBo = productQohBo;
}
//this method need to be transactional
public void save(Product product, int qoh){
productDao.save(product);
System.out.println("Product Inserted");
ProductQoh productQoh = new ProductQoh();
productQoh.setProductId(product.getProductId());
productQoh.setQty(qoh);
productQohBo.save(productQoh);
System.out.println("ProductQoh Inserted");
}
}
Spring 的 bean 配置文件。
運行它
Product product = new Product();
product.setProductCode("ABC");
product.setProductDesc("This is product ABC");
ProductBo productBo = (ProductBo)appContext.getBean("productBo");
productBo.save(product, 100);
假設save() 不具有事務功能,如果異常拋出由productQohBo.save(),鈄只插入一條記錄到「product」表,沒有記錄將被插入到「productQoh'表。這是一個嚴重的問題,在數據庫中打破數據一致性。
3.事務管理
聲明「TransactionInterceptor' bean,以及」HibernateTransactionManager' Hibernate事務,並且通過必要的屬性。
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="save">PROPAGATION\_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
事務屬性
在事務攔截器,必須定義的事務的屬性「傳播行爲」應使用。這意味着,如果一個事務「ProductBoImpl.save()方法被調用另外的」productQohBo.save()'方法,事務應該怎麼傳播?它能繼續在現有的事務中運行?或者爲自己開始一個新的事務。
由Spring支持傳播的 7種類型:
- PROPAGATION_REQUIRED – 支持當前事務;如果不存在則創建一個新的。
- PROPAGATION_SUPPORTS – 支持當前事務;如果不存在執行非事務。
- PROPAGATION_MANDATORY – 支持當前事務;如果當前不存在事務拋出異常。
- PROPAGATION_REQUIRES_NEW – 創建一個新的事務,如果當前事務暫停。
- PROPAGATION_NOT_SUPPORTED – 不支持當前的事務;而始終執行非事務。
- PROPAGATION_NEVER – 不支持當前的事務;如果當前事務存在則拋出異常。
- PROPAGATION_NESTED – 如果當前存在事務嵌套事務中執行,表現與 PROPAGATION_REQUIRED 一樣。
在大多數情況下,可能只需要使用PROPAGATION_REQUIRED。
此外,必須定義方法來支持這個事務屬性。方法名支持通配符格式,save*會匹配所有的方法名 以save(...)開始的方法 。
事務管理器
在Hibernate事務,需要使用 HibernateTransactionManager 。 如果只對付純JDBC,useDataSourceTransactionManager; 而如果是 JTA,需要使用 JtaTransactionManager 。
4.代理工廠bean
創建一個新的代理工廠bean的ProductBo,並設置「interceptorNames」屬性。
運行它
Product product = new Product();
product.setProductCode("ABC");
product.setProductDesc("This is product ABC");
ProductBo productBo = (ProductBo)appContext.getBean("productBoProxy");
productBo.save(product, 100);
代理 bean' productBoProxy'和 save()方法是支持事務,現在,裏面productBo.save()方法任何異常會導致整個事務回滾,沒有數據會被插入到數據庫中。
下載代碼 – http://pan.baidu.com/s/1qXynbo4