程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java學習雜談(十二)--ORM

Java學習雜談(十二)--ORM

編輯:關於JAVA

這是最後一篇Java雜談了,以ORM框架的談論收尾,也算是把J2ee的最後一方面給涵蓋到了,之所以這麼晚才總結出ORM這方面,一是筆者這兩周比較忙,另一方面也想善始善終,仔細的先自己好好研究一下ORM框架技術,不想草率的敷衍了事。

其實J2ee的規范指南裡面就已經包括了一些對象持久化技術,例如JDO(Java Data Object)就是Java對象持久化的新規范,一個用於存取某種數據倉庫中的對象的標准化API,提供了透明的對象存儲,對開發人員來說,存儲數據對象完全不需要額外的代碼(如JDBC API的使用)。這些繁瑣的工作已經轉移到JDO產品提供商身上,使開發人員解脫出來,從而集中時間和精力在業務邏輯上。另外,JDO很靈活,因為它可以在任何數據底層上運行。JDBC只是面向關系數據庫(RDBMS)JDO更通用,提供到任何數據底層的存儲功能,比如關系數據庫、文件、XML以及對象數據庫(ODBMS)等等,使得應用可移植性更強。我們如果要理解對象持久化技術,首先要問自己一個問題:為什麼傳統的JDBC來持久化不再能滿足大家的需求了呢?

筆者認為最好是能用JDBC真正編寫過程序了才能真正體會ORM的好處,同樣的道理,真正拿Servlet/Jsp做過項目了才能體會到Struts、Spring等框架的方便之處。很幸運的是筆者這兩者都曾經經歷過,用混亂的內嵌Java代碼的Jsp加Servlet轉發寫過完整的Web項目,也用 JDBC搭建過一個完整C/S項目的後台。所以現在接觸到新框架才更能體會它們思想和實現的優越之處,回顧從前的代碼,真是丑陋不堪啊。^_^

回到正題,我們來研究一下為什麼要從JDBC發展到ORM.簡單來說,傳統的JDBC要花大量的重復代碼在初始化數據庫連接上,每次增刪改查都要獲得 Connection對象,初始化Statement,執行得到ResultSet再封裝成自己的List或者Object,這樣造成了在每個數據訪問方法中都含有大量冗余重復的代碼,考慮到安全性的話,還要加上大量的事務控制和log記錄。雖然我們學習了設計模式之後,可以自己定義Factory來幫助減少一部分重復的代碼,但是仍然無法避免冗余的問題。其次,隨著OO思想深入人心,連典型的過程化語言Perl等都冠冕堂皇的加上了OO的外殼,何況是 Java中繁雜的數據庫訪問持久化技術呢?強調面向對象編程的結果就是找到一個橋梁,使得關系型數據庫存儲的數據能准確的映射到Java的對象上,然後針對Java對象來設計對象和方法,如果我們把數據庫的Table當作Class,Record當作Instance的話,就可以完全用面向對象的思想來編寫數據層的代碼。於是乎,Object Relationship Mapping的概念開始普遍受到重視,盡管很早很早就已經有人提出來了。

缺點我們已經大概清楚了,那麼如何改進呢?對症下藥,首先我們要解決的是如何從Data Schema准備完美的映射到Object Schema,另外要提供對數據庫連接對象生命周期的管理,對事務不同粒度的控制和考慮到擴展性後提供對XML、Properties等可配置化的文件的支持。到目前為止,有很多框架和技術在嘗試著這樣做。例如似乎是封裝管理得過了頭的EJB、很早就出現目前已經不在開發和升級了的Apache OJB、首先支持Manual SQL的iBATIS,還有公認非常優秀的Hibernate等等。在分別介紹它們之前,我還想反復強調這些框架都在試圖做什麼:

畢竟Java Object和數據庫的每一條Record還是有很大的區別,就是類型上來說,DB是沒有Boolean類型的。而Java也不得不用封裝類(Integer、Double等)為了能映射上數據庫中為null的情況,畢竟Primitive類型是沒有null值的。還有一個比較明顯的問題是,數據庫有主鍵和外鍵,而Java中仍然只能通過基本類型來對應字段值而已,無法規定Unique等特征,更別提外鍵約束、事務控制和級聯操作了。另外,通過Java    Object預設某Field值去取數據庫記錄,是否在這樣的記錄也是不能保證的。真的要設計到完全映射的話,Java的Static被所有對象共享的變量怎麼辦?在數據庫中如何表現出來……

我們能看到大量的問題像一座座大山橫在那些框架設計者們面前,他們並不是沒有解決辦法,而是從不同的角度去考慮,會得到很多不同的解決方案,問題是應該采取哪一種呢?甚至只有等到真正設計出來了投入生產使用了,才能印證出當初的設想是否真的能為項目開發帶來更多的益處。筆者引用一份文檔中提到一個健壯的持久化框架應該具有的特點:

A    robust persistence    layer    should    support——

1.Several    types    of    persistence    mechanism

2.Full    encapsulation    of    the    persistence    mechanism.

3.Multi-object    actions

4.Transactions    Control

5.Extensibility

6.Object identifiers

7.Cursors:    logical    connection    to    the    persistence    mechanism

8.Proxies:    commonly    used    when    the    results    of    a    query    are    to    be    displayed    in    a    list

9.Records:   avoid   the   overhead    of    converting    database    records to    objects    and    then    back    to    records

10.Multi    architecture

11.Various    database    version    and/or    vendors

12.Multiple    connections

13.Native    and non-native    drivers

14.Structured    query    l

現在來簡短的介紹一下筆者用過的一些持久化框架和技術,之所以前面強調那麼多共通的知識,是希望大家不要盲從流行框架,一定要把握它的本質和卓越的思想好在哪裡。

1.Apache OJB

OJB代表Apache Object Relational Bridge,是Apache開發的一個數據庫持久型框架。它是基於J2ee規范指南下的持久型框架技術而設計開發的,例如實現了ODMG 3.0規范的API,實現了JDO規范的API,核心實現是Persistence Broker API.OJB使用XML文件來實現映射並動態的在Metadata layer聽過一個Meta-Object-Protocol(MOP)來改變底層數據的行為。更高級的特點包括對象緩存機制、鎖管理機制、Virtual    代理、事務隔離性級別等等。舉個OJB Mapping的簡單例子ojb-repository.xml:

<class-descriptor class="com.ant.Employee" table="EMPLOYEE"> <field-descriptor name="id" column="ID" jdbc-type="INTEGER" primarykey="true" autoincrement="true"/>

   <field-descriptor name="name" column="NAME" jdbc-type="VARCHAR"/> </class-descrptor>

   <class-descriptor class="com.ant.Executive" table="EXECUTIVE"> <field-descriptor name="id" column="ID" jdbc-type="INTEGER" primarykey="true" autoincrement="true"/>

   <field-descriptor name="department" column="DEPARTMENT" jdbc-type="VARCHAR"/>

   <reference-descriptor name="super" class-ref="com.ant.Employee"> <foreignkey field-ref="id"/> </reference-descriptor> </class-descrptor>

2.iBATIS

iBATIS最大的特點就是允許用戶自己定義SQL來組配Bean的屬性。因為它的SQL語句是直接寫入XML文件中去的,所以可以最大程度上利用到 SQL語法本身能控制的全部特性,同時也能允許你使用特定數據庫服務器的額外特性,並不局限於類似SQL92這樣的標准,它最大的缺點是不支持枚舉類型的持久化,即把枚舉類型的幾個對象屬性拼成與數據庫一個字段例如VARCHAR對應的行為。這裡也舉一個Mapping文件的例子sqlMap.xml:

<sqlMap> <typeAlias type="com.ant.Test" alias="test"/>

   <resultMap class="test" id="result"> <result property="testId" column="TestId"/> <result property="name" column="Name"/> <result property="date" column="Date"/> </resultMap>

   <select id="getTestById" resultMap="result" parameterClass="int"> select * from Test where TestId=#value# </select>

   <update id="updateTest" parameterClass="test"> Update Tests set Name=#name#,Date="date" where TestId=#testId# </update> </sqlMap>

3.Hibernate

Hibernate無疑是應用最廣泛最受歡迎的持久型框架,它生成的SQL語句是非常優秀。雖然一度因為不能支持手工SQL而性能受到局限,但隨著新一代 Hibernate    3.x推出,很多缺點都被改進,Hibernate也因此變得更加通用而時尚。同樣先看一個Mapping文件的例子customer.hbm.xml來有一個大概印象:

<hibernate-mapping> <class name="com.ant.Customer" table="Customers"> <id name="customerId" column="CustomerId" type="int" unsaved-value="0"> <generator class="sequence"> <param name="sequence">  Customers_CustomerId_Seq  </param> </generator> </id>

   <property name="firstName" column="FirstName"/> <property name="lastName" column="LastName"/>

   <set name="addresses" outer-join="true"> <key column="Customer"/> <one-to-many class="com.ant.Address"/> </set>

   …

   </class>

   </hibernate-mapping>

Hibernate有很多顯著的特性,最突出的就是它有自己的查詢語言叫做HQL,在HQL中select from的不是Table而是類名,一方面更加面向對象,另外一方面通過在hibernate.cfg.xml中配置Dialect為HQL可以使得整個後台與數據庫脫離耦合,因為不管用那種數據庫我都是基於HQL來查詢,Hibernate框架負責幫我最終轉換成特定數據庫裡的SQL語句。另外 Hibernate在Object-Caching這方面也做得相當出色,它同時管理兩個級別的緩存,當數據被第一次取出後,真正使用的時候對象被放在一級緩存管理,這個時候任何改動都會影響到數據庫;而空閒時候會把對象放在二級緩存管理,雖然這個時候與數據庫字段能對應上但未綁定在一起,改動不會影響到數據庫的記錄,主要目的是為了在重復讀取的時候更快的拿到數據而不用再次請求連接對象。其實關於這種緩存的設計建議大家研究一下Oracle的存儲機制(原理是相通的),Oracle犧牲了空間換來時間依賴於很健壯的緩存算法來保證最優的企業級數據庫訪問速率。

以上是一些Mapping的例子,真正在Java代碼中使用多半是繼承各個框架中默認的Dao實現類,然後可以通過Id來查找對象,或者通過 Example來查找,更流行的是更具Criteria查找對象。Criteria是完全封裝了SQL條件查詢語法的一個工具類,任何一個查詢條件都可以在Criteria中找到方法與之對應,這樣可以在Java代碼級別實現SQL的完全控制。另外,現在許多ORM框架的最新版本隨著JDk 5.0加入Annotation特性都開始支持用XDoclet來自動根據Annotation來生成XML配置文件了。

筆者不可能詳細的講解每一個框架,也許更多的人在用Hibernate,筆者是從OJB開始接觸ORM技術的,它很原始卻更容易讓人理解從JDBC到 ORM的過渡。更多的細節是可以從官方文檔和書籍中學到的,但我們應該更加看中它們設計思想的來源和閃光點,不是盲從它們的使用方法。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved