歡迎您光臨本站 註冊首頁

當Spring遇到Hibernate的時候

←手機掃碼閱讀     火星人 @ 2014-03-10 , reply:0

1) 介紹

最近我參與了北美一家銀行的審計系統的後台軟體設計和開發工作,除了使用Web Service以外,我們集成了Spring和Hibernate,通過Spring的HibernateTemplate實現了對資料庫數據的存取.眾所周知Hibernate是一種廣泛應用的一種強大的數據持久層技術, 另一方面Spring作為支持IOC的依賴注入框架, 其優點是能夠非常好地集成大多數主流技術. 本文我們將討論如何集成 Spring 和Hibernate.

2) Spring和Hibernate基礎

在我們實際進入集成這兩個技術之前,讓我們理解這種集成需求,大家都知道Hibernate是一種位於應用和資料庫之間的強大的ORM 工具. 它可使應用以獨立平台的方式從各種資料庫訪問數據,對應用來說沒有必要依賴於低級DBC 細節如管理連接, 處理statements 和result sets. 所有訪問特定數據源的細節很容易在Xml文件中配置,另一個好處是Hibernate和J2SE和J2EE應用兼容得很好.

使用Hibernate 問題之一是使用Hibernate Framework訪問資料庫的客戶應用必須依賴Hibernate APIs如Configuration, SessionFactory and Session. 這些個對象在應用代碼中持續擴散.應用代碼必須用手工維護和管理這些對象.但是在Spring的環境, 業務對象通過IOC的幫助下是能夠通過配置完成的,簡單地說,一個對象狀態能夠從應用代碼中分離.意思是現在使用Hibernate 對象作為Spring Beans是可能的,他們能夠得到Spring提供的所有方便.

3) 集成Sample

我們沒有打算研究Spring包里集成的各種API,我們想通過實例源碼來學習和理解這些APIs. 下列部分包括了集成Spring-Hiberante 的每個步驟並附有詳細的解釋.

3.1) 創立資料庫

下面的應用使用Oracle資料庫. Oracle10g的express版本可以從http://www.oracle.com/technology/products/database/xe/index.html免費下載,安裝后, 先用管理員身份登錄和創建用戶schema,username and password,再以用戶身份登錄後去SQL command 或SQL Script運行以下SQL statement :create table Activitylog(id varchar(10), name varchar(20), taskcode varchar(3), tasktime timestamp);現在一個空表已創立.

3.2) ActivityLog類

現在讓我們創建叫做Activitylog POJO代碼用於存儲從Activitylog表取出的數據,此類的設計使表'Activitylog'的列名將被映射到Java類Activitylog適當類型的變數名. 可使用ant工具或plug-in產生,Activitylog類完整的代碼列舉如下:

package com.xxx.audit.pojo;
public class Activitylog {
private String id;
private String name;
private String taskcode;
private Timestamp tasktime;
public Activitylog () {
}
public String getId(){
return id;
}
public void setId(String id){
this.id = id;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getTaskcode(){
return taskcode;
}
public void setTaskcode(String taskcode){
this.taskcode = taskcode;
}
public Timestamp getTasktime(){
return tasktime;
}
public void setTasktime(Timestamp tasktime){
this.tasktime = tasktime;
}
public String toString(){
return "Id = " id ", Name = " name ", Taskcode = "
taskcode ", Tasktime = " tasktime;
}
}

注意toString() 方法重寫是為了Activitylog 對象的顯示.

3.3) 創建Hibernate Mapping 文件

我們已經在資料庫中創建了'Activitylog' 表和一個在應用層相應的Java類 class,我們需要創建Hibernate Mapping文件去把'Activitylog' 表映射到'Activitylog' Java 類,'Activitylog' 表的列名映射到'Activitylog' Java 類的變數,可使用ant工具或plug-in產生,讓我們看看Hibernate Mapping文件:

Activitylog.hbm.xml
<?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>
<class name="com.xxxx.audit.pojo.activitylog" table=" activitylog ">
<id name="id" column="Id">
<generator class="assigned"/>
</id>
<property name="name">
<column name="Name"/>
</property>
<property name="taskcode">
<column name="Taskcode"/>
</property>
<property name="tasktime">
<column name="Tasktime"/>
</property>
</class>
</hibernate-mapping>

注意映射文件是一個Xml文件並且它的名字是Activitylog.hbm.xml. 文件名中'hbm' 代表它是Hibernate映射文件. class 標記定義了資料庫表和Java類之間的映射. 'name' 屬性必須指向一個全路徑的Java類名,反之表屬性必須指向資料庫表,接下來的標記定義了列名和對應java變數之間的映射,'id' 標記作為主鍵定義了一行的標識,property標記有一個屬性叫'name' 指向Java變數名, 接下來的是它映射的資料庫表的列名.

3.4) 創立Spring配置文件

這部分處理配置各種Spring需要的信息. 在Spring全部的業務對象在Xml文件中配置,配置的業務對象叫做 Spring Beans.這些Spring Beans可通過IOC維護,讓我們定義一個data source如下,

spring-hibernate.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-2.0.xsd">
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" >
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>


?
</beans>

上面bean定義了一個類型'org.apache.commons.dbcp.BasicDataSource'的data-source. 更重要的是, 它定義了各種訪問資料庫所需要的連接屬性.

現在讓我們定義第二個Spring Bean:SessionFactory.如果你有Hibernate編程經驗, 你將實現SessionFactory Bean 負責去創建Session對象,通過Session對象處理 Transaction 和數據訪問. 現在同樣的SessionFactory Bean必須用Spring的方式進行配置如下,

<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mappingResources">
<list>
<value>com/xxxx/audit/pojo/Activitylog.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>hibernate.dialect=org.hibernate.dialect.Oracle9Dialect</value>
</property>
</bean>

當配置SessionFactory Bean時,我們已經給出兩個強制信息. 一個是data-source 信息包含訪問資料庫的細節;第二個是一個映射文件的列表,他包含了資料庫表和Java類之間的映射信息,我們在第2部分已經定義了他們,在『list』標誌中應用.

第三個重要的Spring Bean是Hibernate Template. 它提供了一個低級數據訪問和操作的包裝,精確地它包含以下方法:insert/delete/update/find資料庫中的數據,對Hibernate Template的配置唯一的變數是SessionFactory Bean對象如下所示:

<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="mySessionFactory"/>
</property>
</bean>

的Bean定義是Dao類,是客戶化的類. 雖然此類必須定義在應用級,它能夠包含任意數量客戶數據訪問方法的封裝,雖然我們知道它是與資料庫交互的 Hibernate Template類,它將是一個Hibernate Template的理想引用.

<bean id="ActivitylogDao" class="javabeat.spring.hibernate.ActivitylogDao">
<property name="hibernateTemplate">
<ref bean="hibernateTemplate"/>
</property>
</bean>

注意一個引用指向 ActivitylogDao類,它是我們以前討論過的.

3.5)定義ActivitylogDao class

如上所述, 這個ActivitylogDao 類能夠包含任意數量的方法供客戶訪問,這個類的設計有兩種選擇,第一種是此類能夠直接依賴Hibernate Template 對象訪問數據,它由IOC注入. 第二種是它你呢個夠利用Hibernate API做數據訪問,此類聲明如下:

ActivitylogDao.java
package javabeat.spring.hibernate;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
public class ActivitylogDao {
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate){
this.hibernateTemplate = hibernateTemplate;
}
public HibernateTemplate getHibernateTemplate(){
return hibernateTemplate;
}

public Activitylog getActivitylog (final String id){
HibernateCallback callback = new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException,SQLException {
return session.load(Activitylog.class, id);
}
};
return (Activitylog)hibernateTemplate.execute(callback);
}

public void saveOrUpdate(final Activitylog activitylog){
HibernateCallback callback = new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException,SQLException {
session.saveOrUpdate(activitylog);
return null;
}
};
hibernateTemplate.execute(callback);
}
}

此類利用了Hibernate API (特別是Session對象) 用於數據訪問.引導Spring訪問 Hibernate API, 我們把邏輯細化,利用Hibernate API 融入Spring知道的著名介面中的特別著名的方法. It happens to be the HibernateCallback 介面使用方法doInHibernate() ,通過傳送一個Hibernate Session 實例, ActivitylogDao類我們已經定義了兩個方法:getActivitylog () and saveOrUpdate .使用Hibernate APIs, 我們定義了HibernateCallback中的代碼, doInHibernate() 方法和通知Spring 執行這些代碼 ,傳送介面引用HibernateTemplate.execute() 方法.

3.6) 客戶端測試程序

SpringHibernateTest.java
package javabeat.spring.hibernate;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;

public class SpringHibernateTest {
public static void main(String[] args) {
Resource resource = new FileSystemResource("./spring-hibernate.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Activitylog activitylog = new Activitylog ();
activitylog.setId("123");
activitylog.setName("ABC");
activitylog.setTaskcode(「8000933120);
activitylog.setTasktime(「2008 11 20 12:02:30 888888」);
ActivitylogDao activitylogDao = (ActivitylogDao)factory.getBean(
"activitylogDao");
activitylogDao.saveOrUpdate(activitylog);
Activitylog actResult = activitylogDao.getActivitylog ("123");
System.out.println(actResult);
}
}

, 我們運行客戶應用訪問測試數據,過程像這樣. 當方法BeanFactory.getBean("ActivitylogDao") 被調用, Spring 找到ActivitylogDao Bean 的指針. 它產生Hibernate Template 對象. 然後初始化Hibernate Template對象, 我們將看到一個Session Factory Bean對象被引用.然後當建立Session Factory Bean對象的時候, 將得到data-source 信息和資料庫表和Java類.

4)總結

本文討論了Spring 和Hibernate的集成. 既討論了需求也討論了它帶來的好處. 通過一個詳細的實例一步步清晰地演示了集成工作.


[火星人 ] 當Spring遇到Hibernate的時候已經有877次圍觀

http://coctec.com/docs/java/show-post-61842.html