2聲明式管理Hibernate本地事務
Spring提供了一種統一的IoC方式來管理Hibernate事務(本地或者分布式事務)。從Spring接手hibernate.cfg.xml(Hibernate的基本配置文件)起,Hibernate事務便輕易交由Spring拖管了。
說明:在上一章介紹IBatis和DAO的時候,曾經針對事務和DAO的關系簡單的進行了探討。通常DAO的粒度應該都是比較細的,即它們只是一些單步的CRUD操作,所以就需要引入一個業務對象來包裹DAO,這樣,就可以在業務對象的基礎上,提供更粗粒度的事務劃分了(比如跨越多個DAO的方法調用進行事務管理)。
為了能對DAO進行更粗粒度的事務控制,需要為其增加一個業務對象。下面給出了該業務對象的接口和實現,如代碼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
}
}
接著給出關于事務策略的配置,其中使用了Spring針對Hibernate3給出的HibernateTransactionManager,它提供了Hibernate的本地事務管理策略,如代碼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>
??????? <!--運行在當前事務范圍內,如果當前沒有啟動事務,那么創建一個新的事務-->
??????? <prop key="business*">PROPAGATION_REQUIRED</prop>
??????? <!--運行在當前事務范圍內,如果當前沒有啟動事務,那么拋出異常-->
??? ???? <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);
}
}