SessionFactory 注入


Spring 可以與Hibernate結合使用,Hibernate的連結、事務管理等是由建立SessionFactory開始的,SessionFactory在 應用程式中通常只需存在一個實例,因而SessionFactory底層的DataSource可以使用Spring的 IoC注入,之後您再注入SessionFactory至相依的物件之中。

例如可以改寫一下 第一個 Hibernate 程式,首先您可以刪除hibernate.cfg.xml,因為這部份可以由Spring在Bean定義檔中撰寫DataSource設定及依賴注入來取代,您可以如下撰寫Spring的Bean定義檔:
  • beans-config.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="dataSource"
class="org.springframework.jdbc.
→ datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/demo</value>
</property>
<property name="username">
<value>caterpillar</value>
</property>
<property name="password">
<value>123456</value>
</property>
</bean>

<bean id="sessionFactory"
class="org.springframework.orm.
→ hibernate3.LocalSessionFactoryBean"
destroy-method="destroy">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>onlyfun/caterpillar/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
</props>
</property>
</bean>

<bean id="userDAO" class="onlyfun.caterpillar.UserDAO">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</beans>

可以看到使用Spring整合Hibernate的好處,可以直接將DataSource注入至 org.springframework.orm.hibernate3.LocalSessionFactoryBean中,至於Hibernate所 需的相關設定,則可透過LocalSessionFactoryBean的相關屬性來設定,像是設定資料庫名稱、使用者名稱、密碼等, LocalSessionFactoryBean會建立SessionFactory的實例,並在執行依賴注入時將這個實例設定給UserDAO。

Hibernate的物件與關聯表格的映射文件之位置與名稱,則指定於"mappingResources"屬性中,如果您自行提供Hibernate本 身的設定檔(hibernate.cfg.xml),您也可以使用 "configLocation"屬性來指定設定檔的位置,而這邊則使用"hibernateProperties"屬性在Spring的 Bean定義檔中直接指定,可以藉此減少對XML組態檔案的管理。

注意!在Spring 1.2.6中可以選擇要整合Hibernate 2或Hibernate 3(Hibernate 3在套件名稱上與Hibernate 2是不相容的),因而在Spring中整合時會有兩種版本的API,例如 org.springframework.orm.hibernate.LocalSessionFactoryBean是在整合Hibernate 2時所使用的類別,而org.springframework.orm.hibernate3.LocalSessionFactoryBean則是在整 合Hibernate 3時使用的類別,因為主要類別名稱是相同的(例如LocalSessionFactoryBean),所以撰寫時要注意套件名稱的設定是否正確。

專案中剩下的部份都不用修改,可以撰寫一個簡單的測試程式來看看如何使用Spring整合Hibernate,進行簡單的資料存取:
  • SpringHibernateDemo.java
package onlyfun.caterpillar;

import org.springframework.context.ApplicationContext;
import org.springframework.context.
support.FileSystemXmlApplicationContext;

public class SpringHibernateDemo {
public static void main(String[] args) {
ApplicationContext context =
new FileSystemXmlApplicationContext(
"beans-config.xml");

// 建立DAO物件
IUserDAO userDAO =
(IUserDAO) context.getBean("userDAO");

User user = new User();
user.setName("caterpillar");
user.setAge(new Integer(30));

userDAO.insert(user);

user = userDAO.find(new Integer(1));

System.out.println("name: " + user.getName());
}
}

執行的結果基本上與HibernateDemo專案是相同的。如果您不是選擇加入spring.jar的話,則您必須個別加入以下的檔案至 Classpath路徑之中:sping-core.jar、spring-beans.jar、spring-context.jar、spring- jdbc.jar、spring-dao.jar、spring-hibernate.jar。

在映射文件的指定上,除了使用"mappingResources"屬性設定之外,您也可以使用"mappingDirectoryLocations"屬性設定,一次指定某個路徑下的所有.hbm.xml檔案,例如:
...
<bean id="sessionFactory"
      class="org.springframework.orm.hibernate3.
              → LocalSessionFactoryBean"
      destroy-method="destroy">
    <property name="dataSource">
        <ref bean="dataSource"/>
    </property>
    <property name="mappingDirectoryLocations">
        <list>
            <value>classpath:/onlyfun/caterpillar</value>
        </list>
    </property>
    ...
</bean>
...