Spring對Hibernate提供宣告式的事務管理,這與之前我們介紹過的事務管理類似,同樣的,我們有簡化的宣告方式與使用interceptor的方式,先來介紹一下簡化的方式。
代碼:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "- "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql: </property>
<property name="username">
<value>caterpillar</value>
</property>
<property name="password">
<value>123456</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean" destroy-method="close">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
net.sf.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">
true
</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="userDAO" class="onlyfun.caterpillar.UserDAO">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
以下這段紅色區塊弄不出來 by cheetah
<bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="inserUser">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
</beans>
以上這段紅色區塊弄不出來 by cheetah
所有的設定說明,您可以參考之前宣告式事務管理介紹的內容,接下來我們要注意的是,由於Spring的宣告事務管理是基於Spring AOP機制實現,而Spring AOP是使用動態代理(dynamic proxy),所以要求代理的對象必須實作介面,所以我們不能直接如下生成bean:
代碼:
ApplicationContext context = new FileSystemXmlApplicationContext("bean.xml");
UserDAO userDAO = (UserDAO) context.getBean("userDAOProxy");
這會發生ClassCastException例外,問題發生的細節,我們留待以後說明AOP再詳細介紹,總之,我們要定義一個介面,讓UserDAO實現介面:
代碼:
package onlyfun.caterpillar;
public interface IUserDAO {
public void insertUser(User user);
}
代碼:
package onlyfun.caterpillar;
import org.springframework.orm.hibernate.support.*;
public class UserDAO extends HibernateDaoSupport implements IUserDAO {
public void insertUser(User user) {
getHibernateTemplate().saveOrUpdate(user);
}
}
然後我們用下面的方式來生成bean,與上例的差別在於我們作了介面轉換:
代碼:
ApplicationContext context = new FileSystemXmlApplicationContext("bean.xml");
IUserDAO userDAO = (IUserDAO) context.getBean("userDAOProxy");
事實上,之前的宣告式事務管理主題中,即使之前的例子中並沒有發生任何的例外,我們最好也是實現介面來實作DAO,依賴於介面也是一個比較好的編程方式。
接下來列出另一個使用interceptor的例子作為參考,直接修改bean定義檔即可:
代碼:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "- "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql: </property>
<property name="username">
<value>caterpillar</value>
</property>
<property name="password">
<value>123456</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean" destroy-method="close">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
net.sf.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">
true
</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<value>
onlyfun.caterpillar.UserDAO.insertUser=PROPAGATION_REQUIRED
</value>
</property>
</bean>
<bean id="userDAO" class="onlyfun.caterpillar.UserDAO">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="userDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>onlyfun.caterpillar.IUserDAO</value>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
<value>userDAO</value>
</list>
</property>
</bean>
</beans>