hibernate的實現原理以及延遲加載

Hibernate是怎樣實現呢?主要是依據反射機制。sql

      如今以一次數據庫查詢操做分析Hibernate實現原理。數據庫

      假設有一個用戶表(tbl_user),表中字段有id,name,sex。同時有一個實體類(User)與其相對應,查詢語句是:  select * from User。api

1.在項目啓動時,Hibernate配置文件中的內容已經存儲在容器中,存儲着表與實體中的關係。緩存

2.在執行select * from User 時,會根據反射機制先找到User的全路徑名稱,進而找到容器中User對應的配置。session

3.因爲配置文件中的實體屬性與數據庫中的字段是對應的,Hibernate會將select * from User 這個hql語句根據不一樣的數據庫方言解析成不一樣的SQL語句(select * from tbl_user)。併發

      大體過程就是這樣,固然,器內部實現的具體過程是比較複雜的,在使用Hibernate進行數據庫操做時,應注意級聯、延遲加載、緩存的使用。app

            

簡單來講就是,利用反射原理,將實體類中的字段按照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缺點:

總的來講,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直接與數據庫交互快.

 

延遲加載:

一.什麼是懶加載?他的做用?

延遲加載,也叫懶加載,它是Hibernate爲提升程序執行效率而提供的一種機制,即只有真正使用該對象的數據時纔會建立。

Hibernate中主要是經過代理(proxy)機制來實現延遲加載。它的具體過程:Hibernate叢數據庫獲取某一個對象數據時、獲取某一個對象的集合屬性值時,或獲取某一個對象所關聯的另外一個對象時,因爲沒有使用該對象的數據,hibernate並非數據庫加載真正的數據,而只是爲該對象建立一個代理對象來表明這個對象,這個對象上的全部屬性都是默認值;只有在真正須要使用該對象的數據時才建立這個真實對象,真正從數據庫中加載它的數據,這樣在某些狀況下,就能夠提升查詢效率。

有以下程序代碼:

User user=(User)session.load(clazz, id);//直接返回的是代理對象

System.out.println(user.getId());//沒有發送sql語句到數據庫加載

user.getName();//建立真實的User實例,併發送sql語句到數據庫中

注意:1.不能判斷User=null;代理對象不可能爲空

代理對象的限制:和代理關聯的session對象,若是session關閉後訪問代理則拋異常。session關閉以前訪問數據庫

2.getId()方法不行由於參數爲ID,getClass()方法不用訪問數據庫就能夠獲得的數據

Hibernate中默認採用延遲加載的狀況主要有如下幾種

1,當調用session上的load()加載一個實體時,會採用延遲加載。

2,當session加載某個實體時,會對這個實體中的集合屬性值採用延遲加載

3當session加載某個實體時,會對這個實體全部單端關聯的另外一個實體對象採用延遲加載。

二.關閉延遲加載

       延遲加載確實會給程序的查詢效率帶來好處,但有時明確知道數據須要當即加載,若是Hibernate先默認使用延遲加載,然後又必須去數據庫加載,反而會下降效率

1.     加載單個實體,若是不須要延遲加載,就可使用session的get()方法。

2.     當session加載某個實體時,不須要對這個實體中的集合屬性值延遲加載,而是要當即加載。這是能夠在映射文件中這個集合的配置元素(set bag list)添加屬性lazy=false;

3.     當session加載某個實體時,不須要對這個實體所單端關聯的另外一個實體對象延遲加載,就能夠在影射文件中針對這個單端關聯的配置元素(<one-to-one><many-to-one>)添加lazy=false;

可以懶加載的對象都是被改寫過的代理對象,當相關聯的session沒有關閉時,訪問這些懶加載對象(代理對象)的屬性(getId和getClass除外)hibernate會初始化這些代理,或用Hibernate.initialize(proxy)來初始化代理對象;當相關聯的session關閉後,再訪問懶加載的對象將出現異常。

相關文章
相關標籤/搜索