Hibernate4實戰 之第六部分:基本實現原理 – JAVA編程語言程序開發技術文章

整體流程
1:通過configuration來讀cfg.xml文件
2:得到SessionFactory 工廠
3:通過SessionFactory 工廠來創建Session實例
4:通過Session打開事務
5:通過session的api操作數據庫
6:事務提交
7:關閉連接
 
說明:以下分方法描述的實現流程並不是Hibernate的完整實現流程,也不是Hibernate的完整實現順序,隻是描述瞭Hibernate實現這些方法的主幹和基本方式,主要是用來理解這些方法背後都發生瞭些什麼,如果需要詳細完整的實現流程,請查閱Hibernate相應文檔和源代碼

 當我們調用瞭session.save(UserModel)後:
1:TO—>PO: Hibernate先在緩存中查找,如果發現在內部緩存中已經存在相同id的PO,就認為這個數據已經保存瞭,拋出例外。
如果緩存中沒有,Hibernate會把傳入的這個TO對象放到session控制的實例池去,也就是把一個瞬時對象變成瞭一個持久化對象。
如果需要Hibernate生成主鍵值,Hibernate就會去生成id並設置到PO上
2:客戶端提交事務或者刷新內存
3:根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
4:根據hbm.xml文件和model來動態的拼sql,如下:
insert into 表名(來自hbm.xml) (字段名列表(來自hbm.xml )) values(對應的值的列表(根據hbm.xml從傳入的model中獲取值))
5:真正用JDBC執行sql,把值添加到數據庫
6:返回這個PO的id。

 

當我們調用瞭session.update(UserModel)後:
1:DO—>PO:首先根據model 的主鍵在hibernate的實例池中查找該對象,找到就拋出錯誤。
如果沒有就DO—>PO,Hibernate會把傳入的這個DO對象放到session控制的實例池去,也就是把一個瞬時對象變成瞭一個持久化對象
2:客戶端提交事務或者刷新內存
3:根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
4:根據hbm.xml文件和model來動態的拼sql,不進行臟數據檢查,如下:
update 表名(來自hbm.xml) set 字段名(來自hbm.xml )=值(根據hbm.xml從傳入的model中獲取值) where 條件
5:真正用JDBC執行sql,把值修改到數據庫
 


當我們調用瞭session.update(UserModel)後:

1:首先根據model 的主鍵在hibernate的實例池中查找該對象,找到就使用該PO對象(用來檢查臟數據)。
2:客戶端提交事務或者刷新內存
3:Hibernate會進行臟數據檢查,如果沒有數據被修改,就不執行下面的步驟瞭。
4:根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
5:根據hbm.xml文件和model來動態的拼sql,進行臟數據檢查(如果開啟瞭dynamic-update的話),如下:
update 表名(來自hbm.xml) set 字段名(來自hbm.xml )=值(根據hbm.xml從傳入的model中獲取值) where 條件
6:真正用JDBC執行sql,把值修改到數據庫

 


Id的生成方式為assigned的情況
當我們調用瞭session.delete(UserModel)後:
1:根據model的主鍵在數據庫裡面查找數據,來保證對象的存在,然後把找到的對象放到內存裡面,如果此時在hibernate的實例池中已經存在對應的實體對象(註意:代理對象不算實體對象),就拋出例外。
2:如果此時在hibernate的實例池中不存在對應的實體對象,那麼就把對象放到內存裡面,但會標識成待刪除的對象,就不可以被load等使用瞭。
3:如果對象還是不存在,那麼就直接返回瞭(註意,這個時候是不拋出例外的)。也就是說,delete之前會執行一個查詢語句。
4:客戶端提交事務或者刷新內存
5:判斷待刪除的PO是否存在,存在才需要刪除,否則不需要刪除
6:如果要刪除,才執行以下的步驟。先根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
7:根據hbm.xml文件和model來動態的拼sql,如下:
delete from 表名(來自hbm.xml) where 主鍵=值(來自model)
8:真正用JDBC執行sql,把數據從數據庫中刪除

 


Id的生成方式為非assigned的情況
n當我們調用瞭session.delete(UserModel)後:
1:根據model的主鍵在hibernate的實例池中查找對應的實體對象(註意:代理對象不算實體對象),找到就拋出例外。
2:如果內存中沒有對應的實體對象,就什麼都不做。
3:客戶端提交事務或者刷新內存
4:先根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
5:根據hbm.xml文件和model來動態的拼sql,如下:
delete from 表名(來自hbm.xml) where 主鍵=值(來自model)
6:真正用JDBC執行sql,把數據從數據庫中刪除,如果數據不存在,就拋出例外
當我們調用瞭session.delete(UserModel)後:
1:根據model的主鍵在hibernate的實例池中查找對應的實體對象(註意:代理對象不算實體對象),找到就使用該對象。
2:如果內存中沒有對應的實體對象,就到數據庫中查找來保證對象的存在,把找到的對象放到內存裡面,而且不會標識成待刪除的對象,可以繼續被load等使用。代理對象也需要去數據庫中查找數據。
3:如果對象還是不存在,那麼就拋出例外。也就是說,delete之前可能會執行一個查詢語句。
4:客戶端提交事務或者刷新內存
5:根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
6:根據hbm.xml文件和model來動態的拼sql,如下:
delete from 表名(來自hbm.xml) where 主鍵=值(來自model)
7:真正用JDBC執行sql,把數據從數據庫中刪除

當我們調用瞭s.load(UserModel.class, “主鍵值");後:
1:根據model類型和主鍵值在一級緩存中查找對象,找到就返回該對象
2:如果沒有找到,判斷是否lazy=true,如果是,那就生成一個代理對象並返回;否則就先查找二級緩存,二級緩存沒有,就查找數據庫。如果是返回代理對象的,在第一次訪問非主鍵屬性的時候,先查找二級緩存,二級緩存中沒有才真正查找數據庫。
3:如果需要查找數據庫的話,會根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
4:根據hbm.xml文件和model來動態的拼sql,如下:
select 字段列表(來自hbm.xml) from 表名(來自hbm.xml) where 主鍵=值
5:真正用JDBC執行sql,把數據從數據庫中查詢出來到rs裡面。如果找不到就報錯
6:從結果集—〉Model,然後返回model
 
註意:load方法開不開事務都可以執行查詢語句。

 

 
當我們調用瞭s.get(UserModel.class, “主鍵值");後:
1:先根據model類型和主鍵值查找緩存,如果存在具體的實體對象,就返回;如果存在實體的代理對象(比如前面load這條數據,但是還沒有使用,那麼load生成的是一個隻有主鍵值的代理對象),那麼查找數據庫,把具體的數據填充到這個代理對象裡面,然後返回這個代理對象,當然這個代理對象此時已經完全裝載好數據瞭,跟實體對象沒有什麼區別瞭。
2:如果要查找數據庫,先根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
3:根據hbm.xml文件和model來動態的拼sql,如下:
select 字段列表(來自hbm.xml) from 表名(來自hbm.xml) where 主鍵=值
4:真正用JDBC執行sql,把數據從數據庫中查詢出來到rs裡面,沒有值就返回null
5:從結果集—〉Model,然後返回model
 
註意:get方法開不開事務都可以執行查詢語句。

 

 

當我們調用瞭q.list();後:
1:對HQL進行語義分析,分析出model來
2:根據model類型和cfg.xml中映射文件的註冊來找到相應的hbm.xml文件
3:根據hbm.xml文件和model,來解析HQL,從而實現動態的把HQL轉換成對應的sql,(從hql—〉sql這個過程是非常復雜的,不但區分不同的數據庫,還包括瞭對sql進行自動的優化),這裡隻能簡單的示例如下:
select 字段列表(來自hbm.xml) from 表名(來自hbm.xml) where 條件
4:真正用JDBC執行sql,把數據從數據庫中查詢出來到rs裡面
5:從結果集—〉Model集合(或對象數組),然後返回model集合(或對象數組)
 
註意:list()方法開不開事務都可以執行查詢語句。

作者: jinnianshilongnian

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。