Hibernate簡(jiǎn)介及其與Spring框架的整合開(kāi)發(fā)

Hibernate介紹

出現(xiàn)背景

在Hibernate等ORM框架出現(xiàn)之前凉倚,Java Web應(yīng)用通常使用JDBC來(lái)進(jìn)行持久層的數(shù)據(jù)庫(kù)訪問(wèn)等操作兼都,但是JDBC存在著很多缺點(diǎn),比如實(shí)現(xiàn)業(yè)務(wù)邏輯的代碼和數(shù)據(jù)庫(kù)訪問(wèn)的代碼摻雜在一起稽寒,使程序結(jié)構(gòu)不清晰扮碧,可讀性差;在程序代碼中嵌入面向關(guān)系的SQL語(yǔ)句瓦胎,使開(kāi)發(fā)人員不能完全運(yùn)用面向?qū)ο蟮乃季S來(lái)編寫(xiě)程序芬萍;業(yè)務(wù)邏輯和關(guān)系數(shù)據(jù)模型綁定尤揣,如果關(guān)系模型發(fā)生變化,需要手工修改程序代碼中所有相關(guān)的SQL語(yǔ)句柬祠,增加了程序維護(hù)的難度等等北戏。

如何解決問(wèn)題

為了解決直接使用JDBC的諸多弊端,以Hibernate為代表的ORM框架應(yīng)運(yùn)而生漫蛔。Hibernate是一個(gè)基于Java的開(kāi)源的持久化中間件嗜愈,對(duì)JDBC做了輕量的封裝。它采用ORM映射機(jī)制莽龟,負(fù)責(zé)實(shí)現(xiàn)Java對(duì)象和關(guān)系數(shù)據(jù)庫(kù)之間的映射蠕嫁,把SQL語(yǔ)句傳給數(shù)據(jù)庫(kù),并且把數(shù)據(jù)庫(kù)返回的結(jié)果封裝成對(duì)象毯盈。Hibernate內(nèi)部封裝了JDBC訪問(wèn)數(shù)據(jù)庫(kù)的操作剃毒,向上層應(yīng)用提供了面向?qū)ο蟮臄?shù)據(jù)庫(kù)訪問(wèn)API,使得Java程序員可以輕松使用面向?qū)ο蟮木幊趟季S去操縱數(shù)據(jù)庫(kù)搂赋,從 95% 的公共數(shù)據(jù)持續(xù)性編程工作中解放出來(lái)赘阀。

Why Hibernate

同樣比較流行的ORM還有MyBatis等,Hibernate相比這些框架有以下優(yōu)勢(shì)脑奠,因此也是我們選擇它作為持久層框架的原因基公,至于Hibernate和MyBatis的詳細(xì)對(duì)比以及MyBatis的優(yōu)勢(shì)可以見(jiàn)這篇文章:數(shù)據(jù)庫(kù)持久層框架iBatis、myBatis宋欺、Hibernate對(duì)比轰豆。

  • Hibernate的DAO層開(kāi)發(fā)比MyBatis簡(jiǎn)單,Mybatis需要維護(hù)SQL和結(jié)果映射齿诞。
  • Hibernate對(duì)對(duì)象的維護(hù)和緩存要比MyBatis好酸休,對(duì)增刪改查的對(duì)象的維護(hù)要方便。
  • Hibernate數(shù)據(jù)庫(kù)移植性很好掌挚,MyBatis的數(shù)據(jù)庫(kù)移植性不好雨席,不同的數(shù)據(jù)庫(kù)需要寫(xiě)不同的SQL。
  • Hibernate有更好的二級(jí)緩存機(jī)制吠式,可以使用第三方緩存。MyBatis本身提供的緩存機(jī)制不佳抽米。
對(duì)象-關(guān)系映射以及應(yīng)用程序的分層體系結(jié)構(gòu)

Hibernate與Spring的整合開(kāi)發(fā)

了解完Hibernate后特占,我將通過(guò)在電影售票系統(tǒng)大作業(yè)中整合Hibernate來(lái)介紹該框架的基本配置與使用,主要的開(kāi)發(fā)環(huán)境為:Intellij IDEA + SpringMVC + Spring +Hibernate + MySQL

數(shù)據(jù)庫(kù)準(zhǔn)備

我們小組使用了MySQL數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)數(shù)據(jù)云茸,并通過(guò)MySQL Workbench這一GUI界面對(duì)數(shù)據(jù)庫(kù)進(jìn)行管理是目。
在開(kāi)始應(yīng)用開(kāi)發(fā)之前,我們先設(shè)計(jì)了基本的數(shù)據(jù)庫(kù)表和相應(yīng)字段标捺,并在表之間設(shè)置外鍵關(guān)聯(lián)關(guān)系懊纳。

基本的數(shù)據(jù)庫(kù)EER模式圖

在IDEA中引入Hibernate

使用Maven創(chuàng)建項(xiàng)目揉抵,在Project Structure的Modules中添加Hibernate模塊并指定配置文件為hibernate.cfg.xml,Maven會(huì)自動(dòng)幫助我們下載相應(yīng)的依賴(lài)包嗤疯。


引入Hibernate

編寫(xiě)Hibernate配置文件

引入Hibernate后冤今,IDE在META-INF目錄下為我們自動(dòng)創(chuàng)建了一個(gè)Hibernate的配置文件,我們可以在其中配置數(shù)據(jù)庫(kù)及緩存相關(guān)的屬性茂缚,比如設(shè)置事務(wù)的自動(dòng)提交屬性為true戏罢,可以簡(jiǎn)化業(yè)務(wù)層的代碼編寫(xiě)。

hibernate.cfg.xml

除了上述的配置文件脚囊,我們還需要其他的配置文件將Spring與Hibernate整合起來(lái)龟糕,這里我創(chuàng)建了infrastructure.xml。

infrastructure.xml

可以看到悔耘,在該xml配置文件中讲岁,我們使用了c3p0數(shù)據(jù)源,c3p0是一個(gè)開(kāi)源的JDBC連接池衬以,它實(shí)現(xiàn)了數(shù)據(jù)源和JNDI綁定缓艳,支持JDBC3規(guī)范和JDBC2的標(biāo)準(zhǔn)擴(kuò)展。同時(shí)我們指定了Spring進(jìn)行組件掃描的基礎(chǔ)包泄鹏,用來(lái)掃描所有Entity注解進(jìn)而實(shí)現(xiàn)Spring的自動(dòng)裝配郎任。再結(jié)合上節(jié)提到的hibernate.cfg.xml,我們就定義好了Hibernate所需要的session工廠bean备籽,通過(guò)session工廠就可以獲取session并調(diào)用Hibernate內(nèi)置的CRUD方法舶治。

在該配置文件的最上方還引用了hibernate.properties,該配置文件定義了數(shù)據(jù)庫(kù)連接的各種屬性车猬,比如url霉猛、用戶名和密碼等供infrastructure.xml引用,可以避免硬編碼屬性珠闰。

hibernate.properties

將數(shù)據(jù)庫(kù)表映射成Java實(shí)體類(lèi)

編寫(xiě)完Hibernate所需的配置文件后惜浅,就可以成功連接到MySQL數(shù)據(jù)庫(kù)。下一步操作就是編寫(xiě)與數(shù)據(jù)庫(kù)表相對(duì)應(yīng)的實(shí)體類(lèi)(持久化類(lèi))伏嗜,而IDEA強(qiáng)大的一點(diǎn)在于坛悉,它可以直接將數(shù)據(jù)庫(kù)表映射成Java實(shí)體類(lèi)并加上基本的注解,從而節(jié)省大量的時(shí)間承绸。

用戶實(shí)體類(lèi)

設(shè)置Hibernate關(guān)聯(lián)映射

數(shù)據(jù)庫(kù)中表與表之間會(huì)存在不同的主外鍵關(guān)聯(lián)關(guān)系肌割,而Hibernate作為ORM框架踪蹬,自然需要將表之間的關(guān)系映射成實(shí)體類(lèi)之間的關(guān)聯(lián)映射關(guān)系。Hibernate為我們提供了@OneToMany、@ManyToOne愤炸、@ManyToMany等多種注解來(lái)表示實(shí)體類(lèi)間的關(guān)聯(lián)關(guān)系。

以上圖中用戶和評(píng)論之間的雙向一對(duì)多關(guān)聯(lián)為例,多端作為關(guān)聯(lián)關(guān)系的主控端,涉及到兩個(gè)實(shí)體的增刪改查操作都應(yīng)由多端完成晤锹,這樣可以減少SQL語(yǔ)句的執(zhí)行,提高數(shù)據(jù)訪問(wèn)性能彤委。一端作為關(guān)聯(lián)關(guān)系的被控端鞭铆,這種被控使用mappedBy屬性來(lái)表明,同時(shí)一端設(shè)置了cascade級(jí)聯(lián)屬性表明在對(duì)用戶進(jìn)行刪除和保存等操作時(shí)葫慎,該操作也會(huì)級(jí)聯(lián)到關(guān)聯(lián)到該用戶的所有評(píng)論實(shí)體衔彻,從而保證業(yè)務(wù)邏輯上的正確性,并且省去了手動(dòng)保存評(píng)論的麻煩偷办。

評(píng)論實(shí)體

而在上圖的評(píng)論實(shí)體中艰额,我們可以相對(duì)應(yīng)地看到針對(duì)User的@ManyToOne注解,而@JoinColumn注解指定了comment表中使用user_id作為外鍵關(guān)聯(lián)到user表的user_id屬性椒涯,從而在關(guān)系層次上建立起了兩個(gè)表之間的聯(lián)系柄沮。

編寫(xiě)B(tài)aseDAO

設(shè)置完實(shí)體類(lèi)之間的關(guān)聯(lián)映射后,就可以進(jìn)入Hibernate的業(yè)務(wù)代碼編寫(xiě)階段废岂。根據(jù)MVC的分層架構(gòu)祖搓,我們將整個(gè)應(yīng)用分為顯示層(View),控制層(Controller)湖苞,業(yè)務(wù)邏輯層(Service)和數(shù)據(jù)訪問(wèn)層(DAO)

分層架構(gòu)示例

其中Controller層負(fù)責(zé)處理請(qǐng)求的路由拯欧,并調(diào)用Service層的業(yè)務(wù)邏輯方法執(zhí)行業(yè)務(wù),而Service層需要調(diào)用DAO層的數(shù)據(jù)訪問(wèn)方法來(lái)實(shí)現(xiàn)與底層數(shù)據(jù)庫(kù)的交互财骨,每一層之間都面向接口編程镐作,保持了較松的耦合性,同時(shí)架構(gòu)清晰隆箩,增強(qiáng)了項(xiàng)目的可維護(hù)性和可伸縮性该贾。

在實(shí)際編程時(shí),我們通常都是自底向上從DAO層開(kāi)始編寫(xiě)代碼捌臊。DAO層封裝了與底層數(shù)據(jù)庫(kù)交互的方法杨蛋,而有一些通用的CRUD方法是每一個(gè)實(shí)體類(lèi)都需要的,因此這些方法可以被封裝成一個(gè)基礎(chǔ)的BaseDAO泛型接口理澎,每一個(gè)實(shí)體類(lèi)各自的DAO接口只需要繼承BaseDAO接口的實(shí)現(xiàn)即可根據(jù)業(yè)務(wù)需求繼續(xù)擴(kuò)展逞力,這也體現(xiàn)了代碼復(fù)用的思想。

BaseDAO

從上圖接口中可以發(fā)現(xiàn)BaseDAO定義了很多不同的查詢(xún)方法糠爬,這也就引出了Hibernate另一方面的重要知識(shí)掏击,即HQL查詢(xún)和標(biāo)準(zhǔn)查詢(xún)。

HQL查詢(xún)

Hibernate 查詢(xún)語(yǔ)言(HQL)是一種面向?qū)ο蟮牟樵?xún)語(yǔ)言秩铆,類(lèi)似于 SQL,但不是去對(duì)表和列進(jìn)行操作,而是面向?qū)ο蠛退鼈兊膶傩浴?HQL 查詢(xún)被 Hibernate 翻譯為傳統(tǒng)的 SQL 查詢(xún)從而對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作殴玛。

盡管能直接使用本地 SQL 語(yǔ)句捅膘,但是應(yīng)該盡可能的使用 HQL 語(yǔ)句,以避免數(shù)據(jù)庫(kù)關(guān)于可移植性的麻煩滚粟,并且體現(xiàn)了 Hibernate 的 SQL 生成和緩存策略寻仗。

在 HQL 中一些關(guān)鍵字比如 SELECT ,F(xiàn)ROM 和 WHERE 等凡壤,是不區(qū)分大小寫(xiě)的署尤,但是一些屬性比如表名和列名是區(qū)分大小寫(xiě)的。

以FROM語(yǔ)句為例展示一下HQL的語(yǔ)法亚侠。
如果想要在存儲(chǔ)中加載一個(gè)完整并持久的對(duì)象曹体,可以使用 FROM 語(yǔ)句。

String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();

在BaseDAO中我編寫(xiě)了一些工具方法來(lái)簡(jiǎn)化HQL查詢(xún)代碼的編寫(xiě)硝烂。

標(biāo)準(zhǔn)查詢(xún)

Hibernate 提供了操縱對(duì)象和相應(yīng)的 RDBMS 表中可用的數(shù)據(jù)的替代方法箕别。一種方法是標(biāo)準(zhǔn)的 API,它允許開(kāi)發(fā)者建立一個(gè)標(biāo)準(zhǔn)的可編程查詢(xún)對(duì)象來(lái)應(yīng)用過(guò)濾規(guī)則和邏輯條件滞谢。

Hibernate Session 接口提供了 createCriteria() 方法串稀,可用于創(chuàng)建一個(gè) Criteria 對(duì)象,使應(yīng)用程序執(zhí)行一個(gè)標(biāo)準(zhǔn)查詢(xún)時(shí)返回一個(gè)持久化對(duì)象的類(lèi)的實(shí)例狮杨。

以下是一個(gè)最簡(jiǎn)單的標(biāo)準(zhǔn)查詢(xún)的例子母截,它只是簡(jiǎn)單地返回對(duì)應(yīng)于員工類(lèi)的每個(gè)對(duì)象:

Criteria cr = session.createCriteria(Employee.class);  
List results = cr.list();

同時(shí)可以使用 Criteria 對(duì)象可用的 add() 方法去添加一個(gè)標(biāo)準(zhǔn)查詢(xún)的限制,限制包括等于(eq)橄教、大于(gt)清寇、小于(lt)等等邏輯謂詞,我也在BaseDAO中將其寫(xiě)成了工具方法颤陶,即根據(jù)條件類(lèi)型來(lái)構(gòu)建Criterion颗管。

同時(shí)我也添加了上述使用到的ConditionType和Condition等輔助類(lèi)來(lái)簡(jiǎn)化標(biāo)準(zhǔn)查詢(xún)的代碼。

利用這些工具類(lèi)和工具方法滓走,可以大大簡(jiǎn)化標(biāo)準(zhǔn)查詢(xún)的代碼垦江,如下所示:

/**
     * 根據(jù)Criterion列表獲取集合對(duì)象
     *
     * @param criterions
     * @return
     */
    @Override
    public List<T> find(Criterion... criterions) {
        return createCriteria(getCurrentSession(), getEntityClass(), criterions).list();
    }

介紹完BaseDAO中的主要方法后,大作業(yè)數(shù)據(jù)訪問(wèn)層的基礎(chǔ)功能就已經(jīng)搭建好了搅方,之后只需根據(jù)業(yè)務(wù)需求擴(kuò)展BaseDAO比吭,進(jìn)而構(gòu)建Service層和Controller層以完成業(yè)務(wù)邏輯的處理,這些內(nèi)容就不再贅述姨涡。
至此Hibernate就成功和Spring進(jìn)行了整合衩藤,并展示了它的強(qiáng)大功能。

參考

Hibernate 教程
Hibernate之條件查詢(xún)(Criteria Queries)
用hibernate+注解實(shí)現(xiàn)各種關(guān)系映射
數(shù)據(jù)庫(kù)持久層框架iBatis涛漂、myBatis赏表、Hibernate對(duì)比
SSH——hibernate 利用注解實(shí)現(xiàn)實(shí)體關(guān)聯(lián)映射詳解
Spring-SpringMVC-Hibernate在IntelliJ與Maven的環(huán)境下搭建
Spring框架教程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末检诗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瓢剿,更是在濱河造成了極大的恐慌逢慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件间狂,死亡現(xiàn)場(chǎng)離奇詭異攻泼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)鉴象,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)忙菠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人纺弊,你說(shuō)我怎么就攤上這事牛欢。” “怎么了俭尖?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵氢惋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我稽犁,道長(zhǎng)焰望,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任已亥,我火速辦了婚禮熊赖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虑椎。我一直安慰自己震鹉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布捆姜。 她就那樣靜靜地躺著传趾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪泥技。 梳的紋絲不亂的頭發(fā)上浆兰,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音珊豹,去河邊找鬼簸呈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛店茶,可吹牛的內(nèi)容都是我干的蜕便。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼贩幻,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼轿腺!你這毒婦竟也來(lái)了两嘴?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吃溅,失蹤者是張志新(化名)和其女友劉穎溶诞,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體决侈,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年喧务,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赖歌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡功茴,死狀恐怖庐冯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坎穿,我是刑警寧澤展父,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站玲昧,受9級(jí)特大地震影響栖茉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜孵延,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一吕漂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尘应,春花似錦惶凝、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至玷犹,卻和暖如春混滔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背箱舞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工遍坟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晴股。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓愿伴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親电湘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子隔节,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容