詳解hibernate4基本實(shí)現(xiàn)原理
整體流程
1:通過configuration來讀cfg.xml文件
2:得到SessionFactory工廠
3:通過SessionFactory工廠來創(chuàng)建Session實(shí)例
4:通過Session打開事務(wù)
5:通過session的api操作數(shù)據(jù)庫
6:事務(wù)提交
7:關(guān)閉連接
說明:以下分方法描述的實(shí)現(xiàn)流程并不是Hibernate的完整實(shí)現(xiàn)流程,也不是Hibernate的完整實(shí)現(xiàn)順序,只是描述了Hibernate實(shí)現(xiàn)這些方法的主干和基本方式,主要是用來理解這些方法背后都發(fā)生了些什么,如果需要詳細(xì)完整的實(shí)現(xiàn)流程,請查閱Hibernate相應(yīng)文檔和源代碼
當(dāng)我們調(diào)用了session.save(UserModel)后:
1:TO--->PO:Hibernate先在緩存中查找,如果發(fā)現(xiàn)在內(nèi)部緩存中已經(jīng)存在相同id的PO,就認(rèn)為這個(gè)數(shù)據(jù)已經(jīng)保存了,拋出例外。
如果緩存中沒有,Hibernate會把傳入的這個(gè)TO對象放到session控制的實(shí)例池去,也就是把一個(gè)瞬時(shí)對象變成了一個(gè)持久化對象。
如果需要Hibernate生成主鍵值,Hibernate就會去生成id并設(shè)置到PO上
2:客戶端提交事務(wù)或者刷新內(nèi)存
3:根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
4:根據(jù)hbm.xml文件和model來動態(tài)的拼sql,如下:
insert into表名(來自hbm.xml) (字段名列表(來自hbm.xml ))values(對應(yīng)的值的列表(根據(jù)hbm.xml從傳入的model中獲取值))
5:真正用JDBC執(zhí)行sql,把值添加到數(shù)據(jù)庫
6:返回這個(gè)PO的id。
當(dāng)我們調(diào)用了session.update(UserModel)后:
1:DO--->PO:首先根據(jù)model的主鍵在hibernate的實(shí)例池中查找該對象,找到就拋出錯(cuò)誤。
如果沒有就DO--->PO,Hibernate會把傳入的這個(gè)DO對象放到session控制的實(shí)例池去,也就是把一個(gè)瞬時(shí)對象變成了一個(gè)持久化對象
2:客戶端提交事務(wù)或者刷新內(nèi)存
3:根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
4:根據(jù)hbm.xml文件和model來動態(tài)的拼sql,不進(jìn)行臟數(shù)據(jù)檢查,如下:
update表名(來自hbm.xml) set 字段名(來自hbm.xml )=值(根據(jù)hbm.xml從傳入的model中獲取值) where條件
5:真正用JDBC執(zhí)行sql,把值修改到數(shù)據(jù)庫
當(dāng)我們調(diào)用了session.update(UserModel)后:
1:首先根據(jù)model的主鍵在hibernate的實(shí)例池中查找該對象,找到就使用該P(yáng)O對象(用來檢查臟數(shù)據(jù))。
2:客戶端提交事務(wù)或者刷新內(nèi)存
3:Hibernate會進(jìn)行臟數(shù)據(jù)檢查,如果沒有數(shù)據(jù)被修改,就不執(zhí)行下面的步驟了。
4:根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
5:根據(jù)hbm.xml文件和model來動態(tài)的拼sql,進(jìn)行臟數(shù)據(jù)檢查(如果開啟了dynamic-update的話),如下:
update表名(來自hbm.xml) set 字段名(來自hbm.xml )=值(根據(jù)hbm.xml從傳入的model中獲取值) where條件
6:真正用JDBC執(zhí)行sql,把值修改到數(shù)據(jù)庫
Id的生成方式為assigned的情況
當(dāng)我們調(diào)用了session.delete(UserModel)后:
1:根據(jù)model的主鍵在數(shù)據(jù)庫里面查找數(shù)據(jù),來保證對象的存在,然后把找到的對象放到內(nèi)存里面,如果此時(shí)在hibernate的實(shí)例池中已經(jīng)存在對應(yīng)的實(shí)體對象(注意:代理對象不算實(shí)體對象),就拋出例外。
2:如果此時(shí)在hibernate的實(shí)例池中不存在對應(yīng)的實(shí)體對象,那么就把對象放到內(nèi)存里面,但會標(biāo)識成待刪除的對象,就不可以被load等使用了。
3:如果對象還是不存在,那么就直接返回了(注意,這個(gè)時(shí)候是不拋出例外的)。也就是說,delete之前會執(zhí)行一個(gè)查詢語句。
4:客戶端提交事務(wù)或者刷新內(nèi)存
5:判斷待刪除的PO是否存在,存在才需要刪除,否則不需要刪除
6:如果要刪除,才執(zhí)行以下的步驟。先根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
7:根據(jù)hbm.xml文件和model來動態(tài)的拼sql,如下:
delete from表名(來自hbm.xml) where 主鍵=值(來自model)
8:真正的JDBC執(zhí)行sql,把數(shù)據(jù)從數(shù)據(jù)庫中刪除
Id的生成方式為非assigned的情況
當(dāng)我們調(diào)用了session.delete(UserModel)
后:
1:根據(jù)model的主鍵在hibernate的實(shí)例池中查找對應(yīng)的實(shí)體對象(注意:代理對象不算實(shí)體對象),找到就拋出例外。
2:如果內(nèi)存中沒有對應(yīng)的實(shí)體對象,就什么都不做。
3:客戶端提交事務(wù)或者刷新內(nèi)存
4:先根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
5:根據(jù)hbm.xml文件和model來動態(tài)的拼sql,如下:
delete from表名(來自hbm.xml) where 主鍵=值(來自model)
6:真正用JDBC執(zhí)行sql,把數(shù)據(jù)從數(shù)據(jù)庫中刪除,如果數(shù)據(jù)不存在,就拋出例外
當(dāng)我們調(diào)用了session.delete(UserModel)
后:
1:根據(jù)model的主鍵在hibernate的實(shí)例池中查找對應(yīng)的實(shí)體對象(注意:代理對象不算實(shí)體對象),找到就使用該對象。
2:如果內(nèi)存中沒有對應(yīng)的實(shí)體對象,就到數(shù)據(jù)庫中查找來保證對象的存在,把找到的對象放到內(nèi)存里面,而且不會標(biāo)識成待刪除的對象,可以繼續(xù)被load等使用。代理對象也需要去數(shù)據(jù)庫中查找數(shù)據(jù)。
3:如果對象還是不存在,那么就拋出例外。也就是說,delete之前可能會執(zhí)行一個(gè)查詢語句。
4:客戶端提交事務(wù)或者刷新內(nèi)存
5:根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
6:根據(jù)hbm.xml文件和model來動態(tài)的拼sql,如下:
delete from表名(來自hbm.xml) where 主鍵=值(來自model)
7:真正用JDBC執(zhí)行sql,把數(shù)據(jù)從數(shù)據(jù)庫中刪除
當(dāng)我們調(diào)用了s.load(UserModel.class,“主鍵值");后:
1:根據(jù)model類型和主鍵值在一級緩存中查找對象,找到就返回該對象
2:如果沒有找到,判斷是否lazy=true,如果是,那就生成一個(gè)代理對象并返回;否則就先查找二級緩存,二級緩存沒有,就查找數(shù)據(jù)庫。如果是返回代理對象的,在第一次訪問非主鍵屬性的時(shí)候,先查找二級緩存,二級緩存中沒有才真正查找數(shù)據(jù)庫。
3:如果需要查找數(shù)據(jù)庫的話,會根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
4:根據(jù)hbm.xml文件和model來動態(tài)的拼sql,如下:
select字段列表(來自hbm.xml) from 表名(來自hbm.xml) where 主鍵=值
5:真正用JDBC執(zhí)行sql,把數(shù)據(jù)從數(shù)據(jù)庫中查詢出來到rs里面。如果找不到就報(bào)錯(cuò)
6:從結(jié)果集---〉Model,然后返回model
注意:load方法開不開事務(wù)都可以執(zhí)行查詢語句。
當(dāng)我們調(diào)用了s.get(UserModel.class, “主鍵值");
后:
1:先根據(jù)model類型和主鍵值查找緩存,如果存在具體的實(shí)體對象,就返回;如果存在實(shí)體的代理對象(比如前面load這條數(shù)據(jù),但是還沒有使用,那么load生成的是一個(gè)只有主鍵值的代理對象),那么查找數(shù)據(jù)庫,把具體的數(shù)據(jù)填充到這個(gè)代理對象里面,然后返回這個(gè)代理對象,當(dāng)然這個(gè)代理對象此時(shí)已經(jīng)完全裝載好數(shù)據(jù)了,跟實(shí)體對象沒有什么區(qū)別了。
2:如果要查找數(shù)據(jù)庫,先根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
3:根據(jù)hbm.xml文件和model來動態(tài)的拼sql,如下:
select字段列表(來自hbm.xml) from 表名(來自hbm.xml) where 主鍵=值
4:真正用JDBC執(zhí)行sql,把數(shù)據(jù)從數(shù)據(jù)庫中查詢出來到rs里面,沒有值就返回null
5:從結(jié)果集---〉Model,然后返回model
注意:get方法開不開事務(wù)都可以執(zhí)行查詢語句。
當(dāng)我們調(diào)用了q.list();后:
1:對HQL進(jìn)行語義分析,分析出model來
2:根據(jù)model類型和cfg.xml中映射文件的注冊來找到相應(yīng)的hbm.xml文件
3:根據(jù)hbm.xml文件和model,來解析HQL,從而實(shí)現(xiàn)動態(tài)的把HQL轉(zhuǎn)換成對應(yīng)的sql,(從hql---〉sql這個(gè)過程是非常復(fù)雜的,不但區(qū)分不同的數(shù)據(jù)庫,還包括了對sql進(jìn)行自動的優(yōu)化),這里只能簡單的示例如下:
select字段列表(來自hbm.xml) from 表名(來自hbm.xml) where 條件
4:真正用JDBC執(zhí)行sql,把數(shù)據(jù)從數(shù)據(jù)庫中查詢出來到rs里面
5:從結(jié)果集---〉Model集合(或?qū)ο髷?shù)組),然后返回model集合(或?qū)ο髷?shù)組)
注意:list()方法開不開事務(wù)都可以執(zhí)行查詢語句。
總結(jié)
以上所述是小編給大家介紹的hibernate4基本實(shí)現(xiàn)原理,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- hibernate4快速入門實(shí)例詳解
- springmvc4+hibernate4分頁查詢功能實(shí)現(xiàn)
- 淺談SpringMVC+Spring3+Hibernate4開發(fā)環(huán)境搭建
- spring mvc4.1.6 spring4.1.6 hibernate4.3.11 mysql5.5.25開發(fā)環(huán)境搭建圖文教程
- struts2.3.24+spring4.1.6+hibernate4.3.11+mysql5.5.25開發(fā)環(huán)境搭建圖文教程
- 解決Hibernate4執(zhí)行save()或update()無效問題的方法
- Hibernate4在MySQL5.1以上版本創(chuàng)建表出錯(cuò) type=InnDB
- SSH框架網(wǎng)上商城項(xiàng)目第1戰(zhàn)之整合Struts2、Hibernate4.3和Spring4.2
相關(guān)文章
Java通過導(dǎo)出超大Excel文件解決內(nèi)存溢出問題
導(dǎo)出excel是咱Java開發(fā)的必備技能,下面這篇文章主要給大家介紹了關(guān)于Java通過導(dǎo)出超大Excel文件解決內(nèi)存溢出問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09詳解spring Boot 集成 Thymeleaf模板引擎實(shí)例
本篇文章主要介紹了spring Boot 集成 Thymeleaf模板引擎實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09springboot使用log4j2異步日志提升性能的實(shí)現(xiàn)方式
這篇文章主要介紹了springboot使用log4j2異步日志提升性能,異步日志實(shí)現(xiàn)方式:將日志存入一個(gè)單獨(dú)的隊(duì)列中,有一個(gè)單獨(dú)的線程從隊(duì)列中獲取日志并寫入磁盤文件,需要的朋友可以參考下2022-05-05使用SpringMVC訪問Controller接口返回400BadRequest
這篇文章主要介紹了使用SpringMVC訪問Controller接口返回400BadRequest,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03java使用jacob.jar將word轉(zhuǎn)pdf
這篇文章主要為大家詳細(xì)介紹了java利用jacob.jar將word轉(zhuǎn)pdf,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12