第二章 java對象持久化技術概述
本章介紹對象持久化的集中模式
1.在業務邏輯層直接通過JDBCAPI來持久化實體域對象,業務邏輯和數據訪問耦合。
2.主動域對象模式
3.ORM模式
4.JDO模式
5.CMP模式
2.1通過JDBC API來持久化實體域對象
Java應用訪問數據庫的最直接的方式就是直接訪問JDBC API,JDBC是Java Database Connectivity的縮寫。
java.sql包提供了JDBC API。在java.sql包中常用的接口和類包括:
DriverManager:驅動程序管理器,負責創建數據庫連接。
Connection:代表數據庫連接。
Statement:負責執行SQL語句。
PreparedStatement:負責執行SQL語句,具有預定義SQL語句的功能。
ResultSet:代表SQL查詢語句的查詢結果集
JDBC驅動程序
Java應用必須通過JDBC驅動程序來和特定的數據庫系統連接。
JDBC驅動程序由數據庫廠商或第三方提供。
負責持久化Customer對象的BusinessService
saveCustomer():把Customer域對象永久保存到數據庫中。
updateCustomer():更新數據庫中Customer域對象的狀態。
deleteCustomer():從數據庫中刪除一個Customer域對象。
loadCustomer():根據特定的OID,把一個Customer域對象從數據庫加載到內存中。
findCustomerByName():根據特定的客戶姓名,把符合查詢條件的Customer域對象從數據庫加載到內存中。
業務邏輯代碼與數據訪問代碼耦合的saveCustomer()方法
con=getConnection(); //獲得數據庫連接
//開始一個數據庫事務
con.setAutoCommit(false);
//以下是業務邏輯代碼,檢查客戶姓名是否爲空
if(customer.getName()==null)
throw new BusinessException("客戶姓名不允許爲空");
//以下是數據訪問代碼,持久化Customer對象
//爲新的CUSTOMERS記錄分配惟一的ID
long customerId=getNextId(con,"CUSTOMERS");
//把Customer對象映射爲面向關係的SQL語句
stmt=con.prepareStatement("insert into CUSTOMERS(ID,NAME,AGE) values(?,?,?)");
stmt.setLong(1,customerId);
stmt.setString(2,customer.getName());
stmt.setInt(3,customer.getAge());
stmt.execute();
業務邏輯代碼與數據訪問代碼耦合的saveCustomer()方法
Iterator iterator =customer.getOrders().iterator();
while (iterator.hasNext() ) {
//以下是業務邏輯代碼,檢查訂單編號是否爲空
Order order=(Order)iterator.next();
if(order.getOrderNumber()==null)
throw new BusinessException("訂單編號不允許爲空");
//以下是數據訪問代碼,級聯持久化Order對象
//爲新的ORDERS記錄分配惟一的ID
long orderId=getNextId(con,"ORDERS");
//把Order對象映射爲面向關係的SQL語句
stmt=con.prepareStatement("insert into ORDERS(ID,ORDER_NUMBER,PRICE,CUSTOMER_ID)values(?,?,?,?)");
stmt.setLong(1,orderId);
stmt.setString(2,order.getOrderNumber());
stmt.setDouble(3,order.getPrice());
stmt.setLong(4,customerId);
stmt.execute();
}
//提交數據庫事務
con.commit();
JDBC編程的缺點
實現業務邏輯的代碼和數據庫訪問代碼摻雜在一起,使程序結構不清晰,可讀性差。
在程序代碼中嵌入面向關係的SQL語句,使開發人員不能完全運用面向對象的思維來編寫程序。
業務邏輯和關係數據模型綁定,如果關係數據模型發生變化,例如修改了CUSTOMERS表的結構,那麼必須手工修改程序代碼中所有相關的SQL語句,這增加了維護軟件的難度。
如果程序代碼中的SQL語句包含語法錯誤,在編譯時不能檢查這種錯誤,只有在運行時才能發現這種錯誤,這增加了調試程序的難度。
數據訪問模式
業務邏輯和數據訪問耦合
ORM模式:在單個組件中負責所有實體域對象的持久化,封裝數據訪問細節。
主動域對象模式:由實體域對象本身負責管理自己的持久化
JDO模式: SUN公司制定的描述對象持久化語義的標準API
CMP模式:由容器負責管理持久化
2.2ORM簡介
對象-關係映射(即Object-Relation Mapping)模式是指在單個組件中負責所有實體域對象的持久化,封轉數據訪問細節。
2.2.1對象-關係映射(Object-Relation Mapping)的概念
ORM解決的主要問題就是對象-關係的映射。域模型和關係模型都分別建立在概念模型的基礎上。域模型是面向對象的,而關係數據模型是面向關係的.
一般情況下,一個持久化類和一個表對應,類的每個實例對應表中的一條記錄。
域模型與關係模型之間存在許多不匹配之處:
域模型中有繼承關係,關係模型不能直接表示繼承關係
域模型中有多對多關聯關係,關係模型通過連接表來表示多對多關聯關係
域模型中有雙向關聯關係,關係模型只有單向參照關係,而且總是many方參照one方。
域模型提倡精粒度模型,而關係模型提倡粗粒度模型
域模型與關係模型之間的不匹配舉例
2.2.3 ORM中間件的使用方法
ORM中間件採用元數據來描述對象-關係映射文件細節,元數據採用XML格式,而且保存在專門的對象-關係映射文件中。
在圖中Session接口向業務邏輯提供了讀寫和刪除域對象的方法,他不公開任何數據訪問細節,SessionImpl實現這個接口。SessionFactroy負責創建Session實例。Hibernate在初始階段把對象-關係映射文件的映射元數據讀入到SessionFactory中。
Public void deleteCustomer(Customer customer)
{
Session sesion=getSession();
Session.delete(customer);
}
Session的delete()方法執行以下步驟:
1>運用Java反射機制,獲得customer對象的類型爲Customer.class
2>參考對象-關係映射元數據,瞭解到和Customer類對應的表爲CUSTOMERS表,此外Customers類和Order類關聯,Order類和ORDER表對應,ORDERS表的外鍵CUSTOMER_ID參照CUSTOMER表的ID主鍵
3>根據以上映射信息,生成SQL語句
Delete from ORDERS where CUSTOMER_ID=?
Delete from CUSTOMERS where ID=?
4>通過JDBC API來執行以上SQL語句
2.2.3 常用的ORM中間件
ORM軟件 |
URL |
Hibernate |
|
TopLink |
http://otn.oracle.com/products/ias/toplink/content.html |
Torque |
http://jakarta.apache.org/turbine/torque/index.html |
ObjectRelatinalBridge |
|
FrontierSuite |
|
Castor |
|
FreeFORM |
|
Expresso |
|
JRelationalFframework |
|
VBSF |
|
Jgrinder |
|
JPA |
直接對輕量級的基於JavaBean形式的實體域進行持久化 |
2.3實體域對象的其他持久化模式
2.3.1主動域對象模式
主動域是實體域對象的一種形式,在它的實現中封裝了關係數據模型和數據訪問細節。
在EJB中分實體Bean分爲:由EJB本身管理持久化,即BMP是主動域對象模型的一個例子,BMP表示有實體EJB本身管理數據訪問細節。
主動域對象模式的優點:
A>在實體域對象中封裝自身的數據訪問細節,過程域對象完全負責業務邏輯,是程序結構清晰
B>如果關係數據模型發生衝突,只需改變主動域對象的代碼,不需要修改過程域對象的業務方法。
主動域對象模式的缺點:
A>在實體域對象的實現中仍然包含sql語句
B>每個實體域對象都負責自身的數據訪問實現。
2.3.2JDO模式
Java Data Objects(JDO)是sun制定的描述對象持久化語義的標準API
採用JDO模式的應用的分層結構
JDO支持關係數據庫。面向對象的數據庫.基於XML的數據庫和其他專用存儲系統
2.3.3 CMP模式
CMP模式表示由EJB容器來管理實體EJB持久化,EJB容器封裝了對象-關係的映射及數據訪問細節。
2.4HibernateAPI簡介
1.提供訪問數據庫的操作(如保存.跟新.刪除和查詢對象)的接口。包括Session.Transacction和Query接口。
2.用於配置Hibernate的接口。包括Configuration
3.使應用程序攔截Hibernate內部發生事件,並做出相關的反應。這些接口:Interceptor.LoadEventListener和SaveEventListener
4.用於擴展Hibernate的功能接口。如UserType.CompositeUserType和IdentifierGenerator接口。
Hibernate內部封裝了JDBC,JTA(JAVA Naming and Directory Interface).JDBC提供底層的數據訪問操作,只要用戶提供相應的JDBC驅動程序,Hibernate可以訪問任何數據庫。JNDI和JTA使Hibernate能夠和j2ee應用服務器集成。
2.4.1hibernate的核心接口
1.Configuration接口是配置Hibernate並且根啓動Hibernate,創建SessionFactory對象。Hiberante應用通過Configuration實例來獲得對象-關係映射文件中文件的元數據,以及動態配置Hibernate的屬性,然後創建sessionFactory的實例
2.SessionFactory接口:初始化hiberante,充當數據存儲源的代理,創建Session對象。一個SessionFactory實例對應一個數據存儲源,應用以SessionFctory中獲取Session實例。
SessionFctory的特點:
1.它是線程安全的,意味着它的同一實例可以被應用的 多個線程共享。
2.它是重量級,這意味着不能隨意的創建或者銷燬它的實例。訪問一個數據庫創建一個SessionFactory,訪問多個就創建多個。(被稱爲重量級的是因爲:1。它需要很大的緩存存放預定義的SQL語句及映射元數據等。還可以配置SessionFactory的緩存插件,被稱爲Hibernate的二次緩存,用來存放被工作單元讀過的數據,將來其他工作單元會重用這些數據,因此這個緩存中的數據能夠被所有工作單元共享,一個工作單元對應一個數據庫事務。)
3.Session接口:負責保存.更新.加載和查詢對象,被稱爲持久化管理器
特點:1。不是線程安全的
2.。是輕量級的,是指創建和銷燬不需要消耗太多的資源
注意:Session有一個緩存,被稱爲Hibernate的一級緩存,它用來存放當前工作單元加載的對象。每個session實例都有自己的緩存,這個session實例的緩存只能被當前工作單元鎖使用
4.Transaction:管理事務。是hibernate的數據庫事務接口,它對底層的事務接口做了封裝,這些遞呈的事務接口包括:
1。JDBCAPI
2。JTA(Java Transaction API)
3.CORBA(Common Object Requet Broker Architecture)API
5.Query和Criteria:執行數據庫查詢.Qurey包裝了一個HQl查詢語句,Criteria接口封裝了基於字符串形式的查詢語句,擅長執行動態的查詢
Hibernte核心接口的類框圖
2.4.2時間處理接口
當程序通過hibernate來加載.保存.跟新和刪除對象時,會觸發Hibernate的攔截器及事件監聽器做出的惡性一處理:
1.事件及事件監聽接口:在HibernateAPI,針對每一種事件都有相應的事件監聽器,如加載對象會觸發org.hibernate.event.LoadEven事件,該事件有org.hibernate.event.LoadeventListener監聽器處理。保存對象觸發org.hibernate.event.SaveEvent事件,該事件由org.hibernate.event.SaveEventListener監聽器處理
2.org.hibernate.Interceptor接口:應用程序可以定義實現Interceptor接口的類,Interceptor實現類負責響應持久化類的實例被加載.保存更新或者刪除的事件。
2.4.3映射類型接口
org.hibernate.type.Type接口表示Hibernate映射類型,用於把域對象映射爲數據庫的關係數據。Hiberante爲Type接口提供了各種實現類:
1.PrimitiveType類型:映射java的基本類型:ByteType。shortType。IntegerType。LongType。
FloatType。DoubleType。characterType和BooleanType這八個類
2.DateType:映射Java日期類型
3.BinaryType:硬塞Byte[]