開始之前
關於本教程
本教程觀察常用的持久性框架,例如 Hibernate、JDO 和普通的 JDBC 3.0 with DB2,並構建一個示例應用程序,整合 Sprint AOP 聲明性事務處理以及 Spring 加 Hibernate 的持久性主干。
前提條件
要下載和運行示例應用程序,首先必須安裝 參考資料 中列出的軟件:
DB2 for Linux, UNIX, and Windows
Spring 框架
JDO、JDBC 和 Hibernate
JDO 簡介
Java Data Object(JDO) API 是標准、基於接口的持久性 Java 模型抽象,可以直接把 Java 域模型實例保存到數據存儲。JDO 是作為 Java Specification Request 的一部分開發的。
開發應用程序時,程序員可以用 Java 編程語言編寫代碼,透明地訪問底層數據存儲,而不需要編寫特定於數據庫的代碼。JDO 技術的特性有:
可移植性:用 JDO API 編寫的應用程序可以運行在多個實現上,不需重新編譯或修改源代碼。
數據庫獨立性:用 JDO API 編寫的應用程序獨立於底層數據庫。
專注於域模型:程序員現在可以專注於他們的域模型,把持久性的細節問題留給 JDO 實現處理。
高性能:程序員可以把持久性的細節委托給 JDO 實現,JDO 實現能夠優化數據訪問模式,從而獲得最佳性能。
JDBC 簡介
Java Database Connectivity(JDBC)API 是作為 Java 2 標准版(J2SE)和 Java 2 企業版(J2EE)平台的關鍵部分出現的。它是 Java 語言以編程方式訪問關系數據庫的基於標准的首要機制。
JDBC API 為程序員提供了極大的靈活性,它提供了對數據庫訪問和緩存管理的直接控制。JDBC API 是項成熟的技術,是一種完善且已得到充分認識的 API,因而得到業內的廣泛認同。
當前的 JDBC 版本(3.O)對舊版本進行了許多必要的改進。DB2 8 及之後的版本完全支持 JDBC 3.0 API。許多特性,例如從數據庫檢索自動生成鍵的能力、打開多個結果集的能力、改進的連接和語句池等都是 JDBC 3.0 中值得稱道的新能力。例如,清單 1 顯示了用 JDBC 3.0 檢索自動生成鍵的代碼片段:
清單 1. JDBC 自動生成鍵
Statement stmt = conn.createStatement();
//Obtain the generated` key from query.
stmt.executeUpdate("INSERT INTO Accounts " +
"(account_name, balance) " +
"VALUES ('Smith Savings Account', 500.00)",
Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
if ( rs.next() ) {
// RetrIEve the auto generated key(s) i.e account_id.
int accountIdkey = rs.getInt(1);
}
Hibernate 簡介
Hibernate 是個強大的、高性能的對象/關系持久性和查詢服務。Hibernate 支持開發符合面向對象風格的持久性類,包括關聯、繼承、多態、復合和集合。Hibernate 允許您用它自己的可移植 SQL 擴展(HQL)表示查詢,也可以用純粹的 SQL 或面向對象方式和示例 API 表示。與其他許多持久性解決方案不同,Hibernate 沒有使您失去使用 SQL 的力量,從而保證了在關系技術上的現有投資和知識一直有效。
Hibernate 是專業的開放源碼項目,比起其他持久性框架,它是應用和接受最為廣泛的框架。像 Spring 這樣的框架提供了對 Hibernate 豐富的支持,在這裡 Spring 的面向方面編程(AOP)框架為開發人員提供了一種聲明式地提供 Hibernate 事務的方式。
Hibernate 用 XML(*.hbm.XML)文件把 Java 類映射到表,把 Java Beans™ 屬性映射到數據庫表。通過 JDBC 支持全部 SQL 數據庫管理系統。Hibernate 可與所有流行的 J2EE 應用服務器和 Web 容器完美集成。
Hibernate 與 JDO 的比較
Hibernate 是一種得到廣泛信任和采用的持久性框架,比 JDO 這樣的規范更成熟。兩個框架在提供持久性時,都可以直接把 Java 域對象保存到持久存儲。由於 JDO 是 Java 規范的一部分,而 Hibernate 具有開放源碼這樣的背景,所以在未來的一段時間內,JDO 仍將在一段時間內得到不同廠商的認同。
如果在 Hibernate 未來的發行版中,能在現有的開放源碼持久性框架上提供對 JDO 的支持,將會很好,這樣就可以把 JDO 規范的強大力量與 Hibernate 可靠的開放源碼特性結合。
開始
在這份教程中,我們將構建一個示例應用程序,它整合了 Spring AOP 的聲明式事務處理,以及 Spring 加 Hibernate 的持久性主干。Spring 是個開放源碼框架,它的創建是為了解決企業應用程序開發的復雜性問題。Spring 是面向控制和面向方面的容器框架的輕量級版本。 Spring 框架提供了 AOP 框架、JDBC DAO 抽象、與 ORM 框架(像 JDO、Hibernate 和 IBATIS SQL 映射)的集成,帶有聲明式事務支持以及構建 Web 應用程序的全功能 MVC 框架。
Spring 的功能可以用於任何 J2EE 服務器,多數功能也可以用於非托管環境。Spring 的一個核心重點就是允許使用未綁定到特定 J2EE 服務上的可重用業務和數據訪問對象。這類對象可以跨 J2EE 環境(Web 或 EJB)、獨立應用程序、測試環境等重用,毫無困難。
我們的示例應用程序代表一個示例企業,其中包含多個部門和員工。我們的示例應用程序需要創建一個名為 orgdb 的 DB2 數據庫,這也是即將介紹的第一步。 SampleOrgDB 容納部門和員工信息。假設部門和員工之間的關聯是 1:N。
創建示例數據庫
本節創建示例企業應用程序要使用的示例數據庫。創建容納部門和員工信息的示例 orgdb 數據庫。創建源表的方法如下:
在 Windows 命令行提示符下,輸入 db2cmd。
輸入以下語句,創建所需數據庫:
db2 create database orgdb
按下 Enter 鍵。
現在我們已經創建好了企業數據庫。容納部門和員工應用程序的表將由示例 Hibernate 應用程序創建。
構建示例應用程序
這一節用 Spring AOP 和 Hibernate 構建並逐步檢查示例企業應用程序,程序將在 DB2 數據庫中保存一個 Java 對象。應用程序允許企業添加部門和屬於這些部門的員工。
為數據庫交互實現 DOA(數據訪問對象)模式。把 Spring AOP 的 TransactionProxyFactoryBean 設置為攔截方法調用,並聲明式地把事務上下文應用到任何事務密集型操作的 DOA 上。
為 DB2 設置 JDBC 數據源和 HibernateSessionFactory
在 Spring 框架中,JDBC DataSource 或 Hibernate SessionFactory 這樣的資源在應用程序上下文中可視為 bean。需要訪問資源的應用程序對象只要通過 bean 引用檢索到這類預定義實例的引用即可(下一節將更詳細地介紹這方面的內容)。在 清單 2 中,可以看到從示例應用程序摘錄的一段代碼:XML 應用程序上下文定義,顯示了如何設置 JDBC DataSource 及其上的 Hibernate SessionFactory。
清單 2 顯示了如何為示例應用程序數據庫(DB2)配置數據源 bean(exampleDataSource)。 driverClassName 代表類型 Type 4 DB2 Java 類(com.ibm.db2.jcc.DB2Driver),url 代表 orgdb 數據庫的位置(jdbc:db2://localhost:50000/orgdb)。將數據庫連接 URL 中包含的主機名(localhost)和端口號(50000)改成 db2 服務器實際安裝的位置。Hibernate.dialect 屬性的值是 “net.sf.hibernate.dialect.DB2Dialect”,它指定 hibernate 使用 DB2 術語,表示您處理的是 DB2 數據庫。對於其他數據庫服務器,這個值會有不同。例如,若要在 Derby 上運行應用程序,值應是 “net.sf.hibernate.dialect.DerbyDialect”。
exampleDataSource bean 被織入 Spring Hibernate 的 SessionFactory。請注意 *.hbm.XML 表示示例應用程序的 OR 映射文件。
清單 2. JDBC 數據源和 HibernateSessionFactory 織入<bean id="exampleDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"><value>com.ibm.db2.jcc.DB2Driver</value></property>
<property name="url"><value>jdbc:db2://localhost:50000/orgdb</value></property>
<property name="username"><value>db2admin</value></property>
<property name="passWord"><value>db2admin</value></property>
</bean>
<bean id="exampleHibernatePropertIEs"
class="org.springframework.beans.factory.config.PropertIEsFactoryBean">
<property name="propertIEs">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.DB2Dialect</prop>
<prop key="hibernate.query.substitutions">true 'T', false 'F'</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.c3p0.minPoolSize">5</prop>
<prop key="hibernate.c3p0.maxPoolSize">20</prop>
<prop key="hibernate.c3p0.timeout">600</prop>
<prop key="hibernate.c3p0.max_statement">50</prop>
<prop key="hibernate.c3p0.testConnectionOnCheckout">false</prop>
</props>
</property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="exampleSessionFactory"
class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref local="exampleDataSource"/></property>
<property name="hibernatePropertIEs">
<ref bean="exampleHibernatePropertIEs" />
</property>
<!-- Must references all OR mapping files. -->
<property name="mappingResources">
<list>
<value>Department.hbm.XML</value>
<value>Employee.hbm.XML</value>
</list>
</property>
</bean>
織入 DAO 層
數據源和會話工廠設置好後,下一步是在織入 DAO(本例中為 DepartmentDAO)以便使用 SessionFactory。接下來,插入 Spring 的 TransactionProxyFactoryBean,它將攔截對應用程序的 DepartmentDAOImpl 對象的方法調用,並聲明式地在上面應用事務上下文。
在這個示例中,DepartmentDAOImpl 類的 addDepartment 方法作為事務的一部分執行,帶有事務屬性 PROPAGATION_REQUIRED。這個屬性相當於 EJB 容器的 TX_REQUIRED。如果希望讓方法總是在事務中運行,可以使用 PROPAGATION_REQUIRED。如果事務已運行,bean 方法會加入這個事務,或者 Spring 輕量級事務管理器會另行啟動一個事務。如果想在調用組件服務時總是啟動新事務,可以使用 PROPAGATION_REQUIRES_NEW 屬性。
清單 3. 編織應用程序的 DAO 和 TransactionManager<!-- Pass the session factory to our DepartmentDAO -->
<bean id="departmentDAOHelper"
class="springexample.db2persist.hibernate.DepartmentDAOHelper">
<property name="departmentDAO"><ref local="departmentDAOTarget"/></property>
</bean>
<bean id="departmentDAO"
class="springexample.db2persist.hibernate.DepartmentDAOImpl">
<property name="sessionFactory"><ref local="exampleSessionFactory"/></property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory"><ref bean="exampleSessionFactory"/></property>
</bean>
<bean id="departmentDAOTarget"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="target"><ref local="departmentDAO"/></property>
<property name="transactionAttributes">
<props>
<prop key="addDepartment">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
有了這個之後,應用程序的織入就完成了。我們來看源代碼。
分析源代碼
如果您還沒有下載文章的源代碼 (DB2SpringHB.zip),請從 下載 部分中下載。把源 zip 文件釋放到桌面的任意位置,例如 c:\。會創建叫做 DB2SpringHB 的文件夾。src\spring 文件夾包含示例應用程序的 Hibernate 映射文件和 Spring 配置文件。src\springexample\db2persist\hibernate 文件包含應用程序的源代碼。
在這裡會找到兩個類,名稱分別為 Department 和 Employee,它們用 Hibernate 的映射文件 Department.hbm.xml 和 Employee.hbm.XML 映射到兩個表。Department 類代表部門信息,Employee 類代表與部門相關的員工信息。前面已經提到過,我們用 1: N 關系為這兩個類建模,其中一個 Department 包含多個 Employee。 清單 4 顯示了 Department 對象的 Hibernate 映射文件。
清單 4. Department 對象的 Hibernate 映射文件 <?XML version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.Net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="springexample.db2persist.hibernate.Department"
table="TBL_DEPARTMENT"
dynamic-update="false"
dynamic-insert="false">
<id
name="id"
column="DEPARTMENT_ID"
type="Java.lang.Long"
unsaved-value="-1"
>
<generator class="native">
</generator>
</id>
<set name ="employees"
inverse = "true"
outer-join="auto"
cascade="all-delete-orphan">
<key column ="EMPLOYEE_ID"/>
<one-to-many class="springexample.db2persist.hibernate.Employee"/>
</set>
<property
name="name"
type="string"
update="false"
insert="true"
column="DEPARTMENT_NAME"
length="60"
not-null="true"
/>
</class>
</hibernate-mapping>
set name="employees" 和一對多類標記表示 Department 和 Employee 之間的關系。generator class="native" 表示 Hibernate 將使用 DB2 自己的標識值生成方法生成主鍵。
分析 DAO 源代碼
DepartmentDAOImpl.Java 代表應用程序的 DAO,它把部門和員工信息插入應用程序數據庫。DepartmentDAOImpl 擴展了 Spring 的 HibernateDaoSupport,它用 Spring 的 HibernateTemplate 簡化了會話管理。這樣就可以通過 getHibernateTemplate() 方法保存或檢索數據。清單 5 所示的 getDepartmentEmployees() 用 HQL 和 getHibernateTemplate().find 方法對 Department 進行 find 操作,找到所有屬於這個部門的員工。
清單 5. DAO 實現public class DepartmentDAOImpl extends HibernateDaoSupport implements DepartmentDAO{
public void addDepartment(Department department) {
getHibernateTemplate().save(department);
}
public Department getDepartmentEmployees(Department department) {
Department dep = null;
List list = getHibernateTemplate().find("from Department department " +
"where department.id = ?" ,
department.getId(),Hibernate.LONG);
if(list.size() > 0){
dep = (Department) list.get(0);
}
return dep;
}
}
現在來看看代碼運行的效果吧!
運行應用程序
要運行示例應用程序,首先必須下載 Spring 框架及其全部相關文件。然後,解壓框架(比如說解壓到 c:\ 目錄下),創建 C:\spring-framework-1.2-rc2 (針對當前發行版)的文件夾。在繼續之前,還必須下載並解壓 apache Ant。
接下來,把源代碼釋放到一個文件夾,例如 c:\,創建 DB2SpringHB 文件夾。再修改 build.XML 文件入口,用實際安裝 Spring 的位置替換 C:\spring-framework-1.2-rc2,用 DB2 Type 4 JDBC 驅動程序所在的位置替換 C:\Installables\IBM\SQLLIB\Java\。
打開命令提示符,更改目錄到 DB2SpringHB,在命令提示符中輸入以下命令:build。
這會構建並運行 CreateDepartmentEmployeeClIEnt 類,該類又創建 Department 類對象,為其填充一些數據,創建 Employee 對象,為它填充數據,並把它添加到 Department 對象。
然後 CreateDepartmentEmployeeClient 調用 DepartmentDAOHelper.addDepartment 類,添加部門和員工信息。一旦插入,CreateDepartmentEmployeeClient 就會調用 DepartmentDAOHelper.getDepartmentEmployees 方法,根據部門 id 得到部門和員工信息。如果 CreateDepartmentEmployeeClIEnt 成功執行,將看到部門名稱和員工信息輸出到控制台。也可以查詢 DB2 數據庫,檢索部門和員工信息。
驗證 DB2 數據庫中的記錄
為了驗證 orgdb 數據庫中的記錄,請執行以下步驟:
在 Windows 命令提示符下,輸入 db2cmd
輸入以下語句: db2 connect to orgdb
db2 select * from tbl_department
db2 select * from tbl_employee
您將看到保存在 DB2 數據庫中的記錄。
至此,您已成功地測試了示例企業應用程序。
結束語
在這份教程中,您學習了在 DB2 數據庫中保持數據的各種方法,並逐步查看了構建示例應用程序的過程,示例應用程序整合了 Spring AOP 的聲明式事務處理,並用 Spring 加 Hibernate 的持久性主干在 DB2 數據庫中保持 Java 對象。這個基本的應用程序成為一個起點,使您快速走上為 DB2 數據庫構建高度可維護、基於持久性的應用程序的大道。
本文示例源代碼或素材下載