1. 程式人生 > >Spring與Hibernate的整合

Spring與Hibernate的整合

1.管理SessionFactory

使用Spring整合Hibernate時我們不需要hibernate.cfg.xml檔案。首先,在applicationContext.xml中配置資料來源(dataSource)bean和session工廠(sessionFactory)bean。其中,在配置session工廠bean時,應該注入三個方面的資訊:

●資料來源bean

●所有持久化類的配置檔案

●Hibernate的SessionFactory的屬性

Hibernate的SessionFactory的屬性資訊又包括兩個內容,一,Hibernate的連線方法;二,不同資料庫連線,啟動時的選擇。

2.為HibernateTemplate注入SessionFactory物件,通過HibernateTemplate來持久化物件

Spring提供了HibernateTemplate,用於持久層訪問,該模板無需開啟Session及關閉Session。它只要獲得SessionFactory的引用,將可以只能地開啟Session,並在持久化訪問結束後關閉Session,程式開發只需完成持久層邏輯,通用的操作(如對資料庫中資料的增,刪,改,查)則有HibernateTemplate完成。

HibernateTemplate有三個建構函式,不論是用哪一種構造,要使HibernateTemplate能完成持久化操作,都必須向其傳入一個SessionFactory的引用。

HibernateTemplate的用法有兩種,一種是常規的用法,另一種是複雜的用。

一,常規的用法

HibernateTemplate通過它自己的delete(Object entity) ,find(String queryString),save(Object entity)等等常用的方法即可完成大多數DAO物件的增,刪,改,查等操作。

二,複雜的用法

HibernateTemplate的複雜的用法是通過如下的兩個方法來完成的:

●Object execute(HibernateCallback action)

●List execute(HibernateCallback action)

這兩個方法都需要一個HibernateCallback例項,程式開發者通過HibernateCallback,可以完全使用Hibernate靈活的方式來訪問資料庫,解決了Spring封裝Hibernate後靈活不足的缺陷。HibernateCallback是一個介面,該介面只有一個方法doInHibernate(org.hibernate.Session session),該方法只有一個引數Session。

通常,程式中採用實現HibernateCallback的匿名內部類來獲取HibernateCallback的例項,方法doInHibernate就是Spring執行的持久化操作。具體的程式碼例項如下:

public class PersonDaoImpl {

private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionFactory) {

this.sessionFactory = sessionFactory;

}

public List findPersonByName(final String name) {

HibernateTemplate hibernateTemplate =

new HibernateTemplate(this.sessionFactory);

return (List)hibernateTemplate.execute(

public Object doInHibernate(Session session) throws Hibernate Exception {

List result =session.createCriteria(Person.clsss)

.add(Restrictions.like("name",name+"%")).list();

return result;

}

);

}

}

注:在方法doInHibernate內可以訪問Session,該Session物件是繫結到該執行緒的Session例項,該方法內的持久層操作與不使用Spring時的持久層操作完全相同,這保證了對於複雜的持久層訪問時,依然可以使用Hibernate的訪問方式。

3.DAO的實現

DAO的實現有兩種方式:一,繼承HibernateDaoSupport實現DAO;二,基於Hibernate3.0實現DAO。

一,繼承HibernateDaoSupport實現DAO

Spring為Hibernate的DAO提供了工具類HibernateDaoSupport。該類主要提供瞭如下兩個方法來方便DAO的實現:

●public final HibernateTemplate getHibernateTemplate()

●public final void setSessionFactory(SessionFactory sessionFactory)

其中,setSessionFactory方法用來接收Spring的ApplicationContext依賴注入的SessionFactory例項;getHibernateTemplate方法則用來根據剛才的SessionFactory產生Session,最後由HibernateTemplate來完成資料庫訪問。

二,基於Hibernate3.0實現DAO

在Hibernate處於事務的管理下時(通常Spring為Hibernate提供事務管理),通過SessionFactory的getCurrentSession()方法可以返回當前的Session,如果當前的JTA事務關聯的Session不存在,則系統開啟一次新的Session,並關聯到當前的JTA事務;如果當前JTA事務關聯的Session已經存在,則直接返回該Session。獲得了當前的Session後就可以進行持久化操作了。

可見,不論使用上面的哪一種方式實現DAO都需要用Spring來注入SessionFactory例項。

4.事務的管理

Hibernate建議所有的對資料庫的訪問都應放在事務內進行,即使進行的只是讀操作。Spring同時支援程式設計式事務和宣告式事務。通常推薦使用宣告式事務。

程式設計式事務管理:

程式設計式事務提供了TransactionTemplate模板類,用的時候必須向其體提供一個PlatformTransactionManager例項。只要TransactionTemplate獲取了PlatformTransactionManager的引用,TransactionTemplate就可以完成事務操作了。TransactionTemplate提供了一個execute方法,它接收一個TransactionCallback例項。TransactionCallback包含如下方法:

●Object doInTransaction(TransactionStatus status)

這是需要有返回值的情況。如果不需要有返回值的話,我們可以用TransactionCallbackWithOutResult類來代替TransactionCallback類,它也有一個方法:

●void doInTransaction(TransactionStatus status)

在這個兩個方法中,在出現異常時,TransactionStatus的例項status可以呼叫setRollbackOnly()方法進行回滾。

一般情況下,向execute方法傳入TransactionCallback或TransactionCallbackWithOutResult例項時,採用的是匿名內部類的形式。

宣告式事務管理:

宣告式事務管理的配置方式通常有三種:

●使用TransactionProxyFactoryBean為目標bean生成事務代理的配置。

●使用BeanNameAutoProxyCreator,根據bean name自動生成事務代理的方式,這是直接利用Spring的AOP框架配置事務代理的方式,需要對Spring的AOP框架有所瞭解。

●使用DefaultAdvisorAutoProxyCreator,這也是直接利用Spring的AOP框架配置事務代理的方式,只是這種配置方式的可讀性不如使用BeanNameAutoProxyCreator的配置方式。
------------------------------------------------------------------

<?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="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/test</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>8093</value>
</property>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>user.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<bean id="userDAO" class="com.dang.action.UserDAOImpl">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>

<bean name="/regedit" class="com.dang.action.RegeditAction">
<property name="userDAO">
<ref bean="userDAO"/>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>

<bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="userDAO" />
</property>
<property name="transactionAttributes">
<props>
<prop key="create*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

</beans>