2聲明式管理Hibernate本地事務(wù)
Spring提供了一種統(tǒng)一的IoC方式來(lái)管理Hibernate事務(wù)(本地或者分布式事務(wù))。從Spring接手hibernate.cfg.xml(Hibernate的基本配置文件)起,Hibernate事務(wù)便輕易交由Spring拖管了。
說(shuō)明:在上一章介紹IBatis和DAO的時(shí)候,曾經(jīng)針對(duì)事務(wù)和DAO的關(guān)系簡(jiǎn)單的進(jìn)行了探討。通常DAO的粒度應(yīng)該都是比較細(xì)的,即它們只是一些單步的CRUD操作,所以就需要引入一個(gè)業(yè)務(wù)對(duì)象來(lái)包裹DAO,這樣,就可以在業(yè)務(wù)對(duì)象的基礎(chǔ)上,提供更粗粒度的事務(wù)劃分了(比如跨越多個(gè)DAO的方法調(diào)用進(jìn)行事務(wù)管理)。
為了能對(duì)DAO進(jìn)行更粗粒度的事務(wù)控制,需要為其增加一個(gè)業(yè)務(wù)對(duì)象。下面給出了該業(yè)務(wù)對(duì)象的接口和實(shí)現(xiàn),如代碼10.25~10.26所示。
package chapter10.spring.hibernate;
import chapter10.hibernate.domain.Category;
public interface StockFacade {
public void business1(Category category);
public void someOtherBusiness();
}
代碼10.26 BusinessFacadeImpl.java
public class BusinessFacadeImpl implements StockFacade {
private StockDao stockDao;
public void setStockDao(StockDao stockDao) {
??? this.stockDao = stockDao;
}
public void business1(Category category) {
??? stockDao.createCategoryCascade(category);
??? stockDao.retrieveProductBy(category);
??? stockDao.deleteCategoryCascade(category);
}
public void someOtherBusiness() {
??? //other implemention
}
}
接著給出關(guān)于事務(wù)策略的配置,其中使用了Spring針對(duì)Hibernate3給出的HibernateTransactionManager,它提供了Hibernate的本地事務(wù)管理策略,如代碼10.27所示。
代碼10.27 transaction-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">①
??? <property name="sessionFactory" >
????? <ref bean="sessionFactory" />
??? </property>
</bean>
<bean id="business"
class="chapter10.spring.hibernate.BusinessFacadeImpl">
??? <property name="stockDao">
????? <ref bean="stockDao"/>
??? </property>
</bean>
<bean id="businessProxy"
??? class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
??? <property name="transactionManager">
????? <ref bean="transactionManager" />
??? </property>
??? <property name="target">
??? ?? <ref bean="business" />
??? </property>
??? <property name="transactionAttributes">
????? <props>
??????? <!--運(yùn)行在當(dāng)前事務(wù)范圍內(nèi),如果當(dāng)前沒(méi)有啟動(dòng)事務(wù),那么創(chuàng)建一個(gè)新的事務(wù)-->
??????? <prop key="business*">PROPAGATION_REQUIRED</prop>
??????? <!--運(yùn)行在當(dāng)前事務(wù)范圍內(nèi),如果當(dāng)前沒(méi)有啟動(dòng)事務(wù),那么拋出異常-->
??? ???? <prop key="someOtherBusiness*">PROPAGATION_MANDATORY</prop>
????? </props>
??? </property>
</bean>
</beans>
代碼10.28 HibernateTransactionUsageTest.java
package chapter10.spring.hibernate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import chapter10.hibernate.domain.Category;
import junit.framework.TestCase;
public class HibernateTransactionUsageTest extends TestCase {
private StockFacade stockBusiness;
protected void setUp() throws Exception {
??? String path = "ch10/spring/hibernate/";
??? ApplicationContext ctx = new ClassPathXmlApplicationContext(
???????? new String[]{path+"dataAccessContext-support-local.xml",
???????????? path+"transaction-context.xml"});
??? stockBusiness = (StockFacade)ctx.getBean("businessProxy");
}
public void testTransctionUsage() {
??? Category category = new Category("RABBIT");
??? category.setName("Rabbit");
??? category.setDescn("Desciption of Rabbit");
??? stockBusiness.business1(category);
}
}