1. 程式人生 > >Hibernate ORM實現原理簡述

Hibernate ORM實現原理簡述

1. 什麼是ORM

ORM的全稱是Object Relational Mapping,即物件關係對映。它的實現思想就是將關係資料庫中表的資料對映成為物件,以物件的形式展現,這樣開發人員就可以把對資料庫的操作轉化為對這些物件的操作。因此它的目的是為了方便開發人員以面向物件的思想來實現對資料庫的操作。

2.什麼是Hibernate

對於Hibernate的稱呼有很多,比如工具、技術、框架以及解決方案等,這些都可以,重要的是大家要知道它的作用。在這裡我習慣性稱它為框架,它是一種能實現ORM的框架。能實現ORM這個功能的框架有很多,Hibernate可以說是這些框架中最流行、最受開發者關注的,甚至連JBoss公司也把它吸收進來,利用它在自己的專案中實現ORM功能。

3.ORM的實現原理

現在在Java領域大家對Hibernate的討論很多,比如它的優缺點、如何應用、錯誤如何解決以及把它和Struts/Spring等框架相結合作為整個系統的解決方案。在這裡我想和大家探討一些更深層次的話題,那就是Hibernate是如何實現ORM的功能?如果讓我們自己開發一款實現ORM功能的框架需要怎麼做?其實這些問題就是圍繞著一個詞,那就是“對映”,如果我們知道如何實現這種對映那麼我們也能夠開發出自己的一款ORM框架。會使用Hibernate的開發人員都知道,在使用它實現ORM功能的時候,主要的檔案有:對映類(.java)、對映檔案(.hbm.xml)以及資料庫配置檔案(.properties或

.cfg.xml),它們各自的作用如下:

  1. 對映類
    它的作用是描述資料庫表的結構,表中的欄位在類中被描述成屬性,將來就可以實現把表中的記錄對映成為該類的物件。

  2. 對映檔案
    它的作用是指定資料庫表和對映類之間的關係,包括對映類和資料庫表的對應關係、表字段和類屬性型別的對應關係以及表字段和類屬性名稱的對應關係等。

  3. 資料庫配置檔案
    它的作用是指定與資料庫連線時需要的連線資訊,比如連線哪中資料庫、登入使用者名稱、登入密碼以及連線字串等。

在這三種主要的檔案中,對映類為普通Java原始檔、對映檔案為XML格式、資料庫配置檔案為Properties格式或者是XML格式。想理解“對映”首先我們需要知道如何解析這三種檔案,即解析XML格式檔案、解析Properties格式檔案和解析Java類檔案。下面我們來分別探討一下如何實現這些檔案的解析。

一、如何解析XML檔案?
前面我們說過對映檔案是XML格式,資料庫配置檔案也可以是XML格式,因此如果能解析XML檔案我們就可以獲取這兩個檔案的資訊。XML檔案格式我簡單做下介紹,比如tom這句就是一個XML格式的描述,name代表節點,節點必須有開始標記和結束標記,在開始標記中我們可以新增一些屬性的宣告比如sex。解析XML的技術可以分為兩類那就是SAX和DOM,這兩種方式的差別和優缺點大家可以上網查閱或者我們會在以後的文章中提出,請大家關注。實現解析XML檔案的功能很方便,我們可以通過下載第三方的一些工具包如xml-apis.jar和xercesImpl.jar等,也可以使用JDK自帶的工具類DocumentBuilderFactory、DocumentBuilder、Document、Element等等,大家可以通過API文擋查閱這些類的說明。通過這些類我們可以把XML檔案的資訊讀入記憶體並通過類中的某些方法獲取指定節點的名字、值、屬性名、屬性值這些資訊。

二、解析Properties檔案

資料庫配置檔案可以是XML格式也可以是Properties格式,Properties檔案一般採用“屬性名=屬性值”的形式描述資訊。如果配置檔案採用Properties檔案描述,我們就需要想辦法解析這種型別的檔案了。想解析Properties檔案大家就需要熟悉Properties這個類了,這個類有一些常用方法比如,load()載入指定檔案並讀取檔案中的屬性資訊,PropertyNames()返回所有屬性名,getProperty()返回指定屬性名的屬性值。通過解析Properties檔案我們可以得到連線資料庫必要的資訊,然後通過底層JDBC技術與資料庫建立連線。

三、解析Java類檔案

通過解析對映檔案和資料庫配置檔案我們可以建立資料庫的連線,可以得到對映類的名字、屬性名、資料庫表名、欄位名以及型別等資訊。要把資料庫中表的資料對映成為物件,首先需要把表中的記錄取出,然後將每個欄位值給對映類物件的每個屬性,這個賦值過程要呼叫物件中的set方法。我們現在通過對映檔案只知道類名和屬性名,如何根據類名和屬性名呼叫相應的set和get方法,是一個關鍵問題。在Java中有一種機制叫反射機制,使用這種機制我們可以得到類的資訊,包括類只用的修飾符、方法、屬性、繼承的父類以及實現介面等資訊。反射機制相關的類有Class、Field、Method以及Constructor等。通過Class的getFields()、getMethods()和getConstructors()方法得到相應的屬性、方法和構造方法。通過Field類的getName()、getType()和getModifiers()方法得到相應的屬性名、屬性型別、屬性修飾符資訊。通過Method類getReturnType()可以獲取方法的返回型別,invoke()方法可以根據給定的方法名和引數值執行物件中對應的方法。我們可以首先通過以上方法獲取類中的屬性名,然後拼寫成setXXX和getXXX方法名,最後根據方法名執行對應的方法,將資料庫資料載入到物件中。

此外要實現Hibernate機制還會涉及到一個技術點,那就是如何獲取資料庫的相關資訊。要實現這個功能,就需要大家瞭解JDBC的DataBaseMetaData類和ResultSetMetaData類,通過這兩個類的方法我們就可以獲取資料庫表的欄位名、型別、大小等相關資訊。在這裡我只是給大家把實現ORM功能的一些關鍵技術提了出來,通過上面介紹大家對ORM機制應該有個大概瞭解,比如通過解析資料庫配置檔案獲取資料庫連線資訊並建立連線,通過解析對映檔案可以獲取對映類名、屬性名、表名以及欄位名等資訊,得到名字後通過反射機制可以得到對映類資訊,呼叫構造方法建立物件,呼叫每個屬性的set方法給物件設值完成資料的裝載。Hibernate就是採用這個過程來實現ORM的,當然Hibernate還使用了事務控制、快取控制等很多技術,大家有興趣的話我們可以以後探討。

4.Hibernate實現原理與缺點

Hibernate是怎樣實現呢?主要是依據反射機制。
現在以一次資料庫查詢操作分析Hibernate實現原理。
假設有一個使用者表(tbl_user),表中欄位有id,name,sex。同時有一個實體類(User)與其相對應,查詢語句是: select * from User。

  • 在專案啟動時,Hibernate配置檔案中的內容已經儲存在容器中,儲存著表與實體中的關係。
  • 在執行select * from User 時,會根據反射機制先找到User的全路徑名稱,進而找到容器中User對應的配置。
  • 由於配置檔案中的實體屬性與資料庫中的欄位是對應的,Hibernate會將select * from User 這個hql語句根據不同的資料庫方言解析成不同的SQL語句(select * from tbl_user)。

大致過程就是這樣,當然,器內部實現的具體過程是比較複雜的,在使用Hibernate進行資料庫操作時,應注意級聯、延遲載入、快取的使用。

簡單來說就是,利用反射原理,將實體類中的欄位按照xml配置或者annotation解析成一條或者多條sql語句,然後放入資料庫執行,說的簡單點,就是這麼個原理,但是內部實現比較複雜。

原理:

  1. 通過Configuration().configure();讀取並解析hibernate.cfg.xml配置檔案
  2. 由hibernate.cfg.xml中的< mapping resource=”com/xx/User.hbm.xml”/>讀取並解析對映資訊
  3. 通過config.buildSessionFactory(); //建立SessionFactory
  4. sessionFactory.openSession(); //開啟Sesssion
  5. session.beginTransaction(); //建立事務Transation
  6. persistent operate 持久化操作
  7. session.getTransaction().commit(); //提交事務
  8. 關閉Session
  9. 關閉SesstionFactory

這個就是原理,不是流程。主要就是一個基於JDBC的主流持久化框架,一個優秀的ORM實現,對JDBC訪問資料庫的程式碼做了封裝,很大程度上監護了DAO層的編碼工作。

缺點:
總的來說,hibernate的缺點主要有以下幾點:

  1. 由於對持久層封裝過於完整,導致開發人員無法對SQL進行優化,無法靈活使用JDBC的原生SQL,Hibernate封裝了JDBC,所以沒有JDBC直接訪問資料庫效率高。要使用資料庫的特定優化機制的時候,不適合用Hibernate
  2. 框架中使用ORM原則,導致配置過於複雜,一旦遇到大型專案,比如300張表以上,配置檔案和內容是非常龐大的,另外,DTO滿天飛,效能和維護問題隨之而來
  3. 如果專案中各個表中關係複雜,表之間的關係很多,在很多地方把lazy都設定false,會導致資料查詢和載入很慢,尤其是級聯查詢的時候。
  4. Hibernate在批量資料處理時有弱勢,對於批量的修改,刪除,不適合用Hibernate,這也是ORM框架的弱點

Hibernate是ORM框架(object-relation maping物件關係對映),它是用來實現JDBC的功能,但是它不能替換JDBC,它是在JDBC基礎上實現的,即Hibernate中已經把JDBC封裝了,最終的程式碼是到HIbernate在傳遞到JDBC在於資料庫交換,所以效能沒有JDBC直接與資料庫互動快。