Google Code Prettify

2016年3月6日 星期日

Hibernate: 與 spring framework 整合


在 JavaEE 領域裡,程式開發不用 spring framework 的非常少,這裡說明 Hibernate 如何與 spring 整合。延續之前例子,設定檔如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd  
        ">
        
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="false"/>
        <property name="locations">
          <list>
            <value>classpath:datasource.properties</value>
          </list>
        </property>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
        p:driverClassName="${jdbc.driverClassName}"
        p:url="${jdbc.url}"
        p:username="${jdbc.username}"
        p:password="${jdbc.password}"
    />

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" 
        p:dataSource-ref="dataSource"
    >
        <property name="mappingResources">
            <list>
                <value>idv/steven/orm/market/Customer.hbm.xml</value>
                <value>idv/steven/orm/market/Goods.hbm.xml</value>
                <value>idv/steven/orm/market/Orders.hbm.xml</value>
                <value>idv/steven/orm/market/Sales.hbm.xml</value>
            </list>
        </property>
        
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
        p:sessionFactory-ref="sessionFactory">
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate"
        p:sessionFactory-ref="sessionFactory"
    />
    
    <bean id="myApp6" class="idv.steven.orm.market.MyApp6">
    </bean>
</beans>
上面的設定檔,與 hibernate 有關的部份,我用紅、綠、藍三色標示出來,整合的方式非常簡單,說明如下:
  1. 在spring 的 bean 設定檔中加入 hibernate 的 sessionFactory (紅色)
  2. 將 transaction 的管理委由 spring 來管理 (綠色)
  3. 宣告一個 HibernateTemplate,這是 spring 提供的一個模板類別,方便程式設計者對資料庫進行 CRUD,這一部份不是必要的,因為 spring 還提供有其它方法,這一篇先說明這個方法。(藍色)
接著寫個測試程式,所有 session 委由 spring 來管理,所以程式的寫法又更精簡了!
 1 public class MyApp6 {
 2     @Autowired
 3     private HibernateTemplate ht;
 4     
 5     public void query() {
 6         Sales s1 = ht.get(Sales.class, "007528");
 7         Iterator<Customer> customer = s1.getCustomer().iterator();
 8         while (customer.hasNext()) {
 9             Customer c = customer.next();
10             System.out.println(c.toString());
11         }
12     }
13     
14     public static void main(String[] args) {
15          ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans-config.xml");
16          MyApp6 myApp6 = context.getBean(MyApp6.class);
17          myApp6.query();
18     }
19 }
第 2~3 行透過 spring 的自動注入機制取得 HibernateTemplate,並使用它來查詢出我們要的資料,這程式執行結果會查詢出編員為007528的這位業務員的所有客戶。
【注意】
Sales.hbm.xml 的設定,lazy 要設定為 false,否則在上面程式的第 7 行會因為延遲載入而發生錯誤!
(錯誤訊息: failed to lazily initialize a collection of role:  could not initialize proxy - no Session)
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="idv.steven.orm.market.entity">
    <class name="Sales" table="SALES">
        <id name="emNo" type="java.lang.String">
            <column name="EMNO" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <set name="customer" inverse="true" lazy="false" fetch="select">
            <!-- foreign key -->
            <key column = "EMNO" />
            <one-to-many class="Customer" />
        </set>
    </class>
</hibernate-mapping>


沒有留言:

張貼留言