原文:https://blog.csdn.net/jackfrued/article/details/44931161
121、解釋一下網(wǎng)絡(luò)應(yīng)用的模式及其特點(diǎn)。
答:典型的網(wǎng)絡(luò)應(yīng)用模式大致有三類(lèi):B/S、C/S、P2P。其中B代表瀏覽器(Browser)、C代表客戶端(Client)、S代表服務(wù)器(Server),P2P是對(duì)等模式,不區(qū)分客戶端和服務(wù)器。B/S應(yīng)用模式中可以視為特殊的C/S應(yīng)用模式,只是將C/S應(yīng)用模式中的特殊的客戶端換成了瀏覽器,因?yàn)閹缀跛械南到y(tǒng)上都有瀏覽器,那么只要打開(kāi)瀏覽器就可以使用應(yīng)用,沒(méi)有安裝、配置、升級(jí)客戶端所帶來(lái)的各種開(kāi)銷(xiāo)。P2P應(yīng)用模式中,成千上萬(wàn)臺(tái)彼此連接的計(jì)算機(jī)都處于對(duì)等的地位,整個(gè)網(wǎng)絡(luò)一般來(lái)說(shuō)不依賴專用的集中服務(wù)器。網(wǎng)絡(luò)中的每一臺(tái)計(jì)算機(jī)既能充當(dāng)網(wǎng)絡(luò)服務(wù)的請(qǐng)求者,又對(duì)其它計(jì)算機(jī)的請(qǐng)求作出響應(yīng),提供資源和服務(wù)。通常這些資源和服務(wù)包括:信息的共享和交換、計(jì)算資源(如CPU的共享)、存儲(chǔ)共享(如緩存和磁盤(pán)空間的使用)等,這種應(yīng)用模式最大的阻力安全性、版本等問(wèn)題,目前有很多應(yīng)用都混合使用了多種應(yīng)用模型,最常見(jiàn)的網(wǎng)絡(luò)視頻應(yīng)用,它幾乎把三種模式都用上了。
補(bǔ)充:此題要跟"電子商務(wù)模式"區(qū)分開(kāi),因?yàn)橛泻芏嗳吮粏?wèn)到這個(gè)問(wèn)題的時(shí)候馬上想到的是B2B(如阿里巴巴)、B2C(如當(dāng)當(dāng)、亞馬遜、京東)、C2C(如淘寶、拍拍)、C2B(如威客)、O2O(如美團(tuán)、餓了么)。對(duì)于這類(lèi)問(wèn)題,可以去百度上面科普一下。
122、什么是Web Service(Web服務(wù))?
答:從表面上看,Web Service就是一個(gè)應(yīng)用程序,它向外界暴露出一個(gè)能夠通過(guò)Web進(jìn)行調(diào)用的API。這就是說(shuō),你能夠用編程的方法透明的調(diào)用這個(gè)應(yīng)用程序,不需要了解它的任何細(xì)節(jié),跟你使用的編程語(yǔ)言也沒(méi)有關(guān)系。例如可以創(chuàng)建一個(gè)提供天氣預(yù)報(bào)的Web Service,那么無(wú)論你用哪種編程語(yǔ)言開(kāi)發(fā)的應(yīng)用都可以通過(guò)調(diào)用它的API并傳入城市信息來(lái)獲得該城市的天氣預(yù)報(bào)。之所以稱之為Web Service,是因?yàn)樗贖TTP協(xié)議傳輸數(shù)據(jù),這使得運(yùn)行在不同機(jī)器上的不同應(yīng)用無(wú)須借助附加的、專門(mén)的第三方軟件或硬件,就可相互交換數(shù)據(jù)或集成。
補(bǔ)充:這里必須要提及的一個(gè)概念是SOA(Service-Oriented Architecture,面向服務(wù)的架構(gòu)),SOA是一種思想,它將應(yīng)用程序的不同功能單元通過(guò)中立的契約聯(lián)系起來(lái),獨(dú)立于硬件平臺(tái)、操作系統(tǒng)和編程語(yǔ)言,使得各種形式的功能單元能夠更好的集成。顯然,Web Service是SOA的一種較好的解決方案,它更多的是一種標(biāo)準(zhǔn),而不是一種具體的技術(shù)。
123、概念解釋:SOAP、WSDL、UDDI。
答:
- SOAP:簡(jiǎn)單對(duì)象訪問(wèn)協(xié)議(Simple Object Access Protocol),是Web Service中交換數(shù)據(jù)的一種協(xié)議規(guī)范。
- WSDL:Web服務(wù)描述語(yǔ)言(Web Service Description Language),它描述了Web服務(wù)的公共接口。這是一個(gè)基于XML的關(guān)于如何與Web服務(wù)通訊和使用的服務(wù)描述;也就是描述與目錄中列出的Web服務(wù)進(jìn)行交互時(shí)需要綁定的協(xié)議和信息格式。通常采用抽象語(yǔ)言描述該服務(wù)支持的操作和信息,使用的時(shí)候再將實(shí)際的網(wǎng)絡(luò)協(xié)議和信息格式綁定給該服務(wù)。
- UDDI:統(tǒng)一描述、發(fā)現(xiàn)和集成(Universal Description, Discovery and Integration),它是一個(gè)基于XML的跨平臺(tái)的描述規(guī)范,可以使世界范圍內(nèi)的企業(yè)在互聯(lián)網(wǎng)上發(fā)布自己所提供的服務(wù)。簡(jiǎn)單的說(shuō),UDDI是訪問(wèn)各種WSDL的一個(gè)門(mén)面(可以參考設(shè)計(jì)模式中的門(mén)面模式)。
提示:關(guān)于Web Service的相關(guān)概念和知識(shí)可以在W3CSchool上找到相關(guān)的資料。
124、Java規(guī)范中和Web Service相關(guān)的規(guī)范有哪些?
答:Java規(guī)范中和Web Service相關(guān)的有三個(gè):
- JAX-WS(JSR 224):這個(gè)規(guī)范是早期的基于SOAP的Web Service規(guī)范JAX-RPC的替代版本,它并不提供向下兼容性,因?yàn)镽PC樣式的WSDL以及相關(guān)的API已經(jīng)在Java EE5中被移除了。WS-MetaData是JAX-WS的依賴規(guī)范,提供了基于注解配置Web Service和SOAP消息的相關(guān)API。
- JAXM(JSR 67):定義了發(fā)送和接收消息所需的API,相當(dāng)于Web Service的服務(wù)器端。
- JAX-RS(JSR 311 & JSR 339 & JSR 370):是Java針對(duì)REST(Representation State Transfer)架構(gòu)風(fēng)格制定的一套Web Service規(guī)范。REST是一種軟件架構(gòu)模式,是一種風(fēng)格,它不像SOAP那樣本身承載著一種消息協(xié)議, (兩種風(fēng)格的Web Service均采用了HTTP做傳輸協(xié)議,因?yàn)镠TTP協(xié)議能穿越防火墻,Java的遠(yuǎn)程方法調(diào)用(RMI)等是重量級(jí)協(xié)議,通常不能穿越防火墻),因此可以將REST視為基于HTTP協(xié)議的軟件架構(gòu)。REST中最重要的兩個(gè)概念是資源定位和資源操作,而HTTP協(xié)議恰好完整的提供了這兩個(gè)點(diǎn)。HTTP協(xié)議中的URI可以完成資源定位,而GET、POST、OPTION、DELETE方法可以完成資源操作。因此REST完全依賴HTTP協(xié)議就可以完成Web Service,而不像SOAP協(xié)議那樣只利用了HTTP的傳輸特性,定位和操作都是由SOAP協(xié)議自身完成的,也正是由于SOAP消息的存在使得基于SOAP的Web Service顯得笨重而逐漸被淘汰。
125、介紹一下你了解的Java領(lǐng)域的Web Service框架。
答:Java領(lǐng)域的Web Service框架很多,包括Axis2(Axis的升級(jí)版本)、Jersey(RESTful的Web Service框架)、CXF(XFire的延續(xù)版本)、Hessian、Turmeric、JBoss SOA等,其中絕大多數(shù)都是開(kāi)源框架。
提示:面試被問(wèn)到這類(lèi)問(wèn)題的時(shí)候一定選擇自己用過(guò)的最熟悉的作答,如果之前沒(méi)有了解過(guò)就應(yīng)該在面試前花一些時(shí)間了解其中的兩個(gè),并比較其優(yōu)缺點(diǎn),這樣才能在面試時(shí)給出一個(gè)漂亮的答案。
?這部分主要是開(kāi)源Java EE框架方面的內(nèi)容,包括Hibernate、MyBatis、Spring、Spring MVC等,由于Struts 2已經(jīng)是明日黃花,在這里就不討論Struts 2的面試題,如果需要了解相關(guān)內(nèi)容,可以參考我的另一篇文章《Java面試題集(86-115)》。此外,這篇文章還對(duì)企業(yè)應(yīng)用架構(gòu)、大型網(wǎng)站架構(gòu)和應(yīng)用服務(wù)器優(yōu)化等內(nèi)容進(jìn)行了簡(jiǎn)單的探討,這些內(nèi)容相信對(duì)面試會(huì)很有幫助。
126、什么是ORM?
答:對(duì)象關(guān)系映射(Object-Relational Mapping,簡(jiǎn)稱ORM)是一種為了解決程序的面向?qū)ο竽P团c數(shù)據(jù)庫(kù)的關(guān)系模型互不匹配問(wèn)題的技術(shù);簡(jiǎn)單的說(shuō),ORM是通過(guò)使用描述對(duì)象和數(shù)據(jù)庫(kù)之間映射的元數(shù)據(jù)(在Java中可以用XML或者是注解),將程序中的對(duì)象自動(dòng)持久化到關(guān)系數(shù)據(jù)庫(kù)中或者將關(guān)系數(shù)據(jù)庫(kù)表中的行轉(zhuǎn)換成Java對(duì)象,其本質(zhì)上就是將數(shù)據(jù)從一種形式轉(zhuǎn)換到另外一種形式。
127、持久層設(shè)計(jì)要考慮的問(wèn)題有哪些?你用過(guò)的持久層框架有哪些?
答:所謂"持久"就是將數(shù)據(jù)保存到可掉電式存儲(chǔ)設(shè)備中以便今后使用,簡(jiǎn)單的說(shuō),就是將內(nèi)存中的數(shù)據(jù)保存到關(guān)系型數(shù)據(jù)庫(kù)、文件系統(tǒng)、消息隊(duì)列等提供持久化支持的設(shè)備中。持久層就是系統(tǒng)中專注于實(shí)現(xiàn)數(shù)據(jù)持久化的相對(duì)獨(dú)立的層面。
持久層設(shè)計(jì)的目標(biāo)包括:
- 數(shù)據(jù)存儲(chǔ)邏輯的分離,提供抽象化的數(shù)據(jù)訪問(wèn)接口。
- 數(shù)據(jù)訪問(wèn)底層實(shí)現(xiàn)的分離,可以在不修改代碼的情況下切換底層實(shí)現(xiàn)。
- 資源管理和調(diào)度的分離,在數(shù)據(jù)訪問(wèn)層實(shí)現(xiàn)統(tǒng)一的資源調(diào)度(如緩存機(jī)制)。
- 數(shù)據(jù)抽象,提供更面向?qū)ο蟮臄?shù)據(jù)操作。
持久層框架有:
- Hibernate
- MyBatis
- TopLink
- Guzz
- jOOQ
- Spring Data
- ActiveJDBC
128、Hibernate中SessionFactory是線程安全的嗎?Session是線程安全的嗎(兩個(gè)線程能夠共享同一個(gè)Session嗎)?
答:SessionFactory對(duì)應(yīng)Hibernate的一個(gè)數(shù)據(jù)存儲(chǔ)的概念,它是線程安全的,可以被多個(gè)線程并發(fā)訪問(wèn)。SessionFactory一般只會(huì)在啟動(dòng)的時(shí)候構(gòu)建。對(duì)于應(yīng)用程序,最好將SessionFactory通過(guò)單例模式進(jìn)行封裝以便于訪問(wèn)。Session是一個(gè)輕量級(jí)非線程安全的對(duì)象(線程間不能共享session),它表示與數(shù)據(jù)庫(kù)進(jìn)行交互的一個(gè)工作單元。Session是由SessionFactory創(chuàng)建的,在任務(wù)完成之后它會(huì)被關(guān)閉。Session是持久層服務(wù)對(duì)外提供的主要接口。Session會(huì)延遲獲取數(shù)據(jù)庫(kù)連接(也就是在需要的時(shí)候才會(huì)獲?。榱吮苊鈩?chuàng)建太多的session,可以使用ThreadLocal將session和當(dāng)前線程綁定在一起,這樣可以讓同一個(gè)線程獲得的總是同一個(gè)session。Hibernate 3中SessionFactory的getCurrentSession()方法就可以做到。
129、Hibernate中Session的load和get方法的區(qū)別是什么?
答:主要有以下三項(xiàng)區(qū)別:
① 如果沒(méi)有找到符合條件的記錄,get方法返回null,load方法拋出異常。
② get方法直接返回實(shí)體類(lèi)對(duì)象,load方法返回實(shí)體類(lèi)對(duì)象的代理。
③ 在Hibernate 3之前,get方法只在一級(jí)緩存中進(jìn)行數(shù)據(jù)查找,如果沒(méi)有找到對(duì)應(yīng)的數(shù)據(jù)則越過(guò)二級(jí)緩存,直接發(fā)出SQL語(yǔ)句完成數(shù)據(jù)讀??;load方法則可以從二級(jí)緩存中獲取數(shù)據(jù);從Hibernate 3開(kāi)始,get方法不再是對(duì)二級(jí)緩存只寫(xiě)不讀,它也是可以訪問(wèn)二級(jí)緩存的。
說(shuō)明:對(duì)于load()方法Hibernate認(rèn)為該數(shù)據(jù)在數(shù)據(jù)庫(kù)中一定存在可以放心的使用代理來(lái)實(shí)現(xiàn)延遲加載,如果沒(méi)有數(shù)據(jù)就拋出異常,而通過(guò)get()方法獲取的數(shù)據(jù)可以不存在。
130、Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分別是做什么的?有什么區(qū)別?
答:Hibernate的對(duì)象有三種狀態(tài):瞬時(shí)態(tài)(transient)、持久態(tài)(persistent)和游離態(tài)(detached),如第135題中的圖所示。瞬時(shí)態(tài)的實(shí)例可以通過(guò)調(diào)用save()、persist()或者saveOrUpdate()方法變成持久態(tài);游離態(tài)的實(shí)例可以通過(guò)調(diào)用 update()、saveOrUpdate()、lock()或者replicate()變成持久態(tài)。save()和persist()將會(huì)引發(fā)SQL的INSERT語(yǔ)句,而update()或merge()會(huì)引發(fā)UPDATE語(yǔ)句。save()和update()的區(qū)別在于一個(gè)是將瞬時(shí)態(tài)對(duì)象變成持久態(tài),一個(gè)是將游離態(tài)對(duì)象變?yōu)槌志脩B(tài)。merge()方法可以完成save()和update()方法的功能,它的意圖是將新的狀態(tài)合并到已有的持久化對(duì)象上或創(chuàng)建新的持久化對(duì)象。對(duì)于persist()方法,按照官方文檔的說(shuō)明:① persist()方法把一個(gè)瞬時(shí)態(tài)的實(shí)例持久化,但是并不保證標(biāo)識(shí)符被立刻填入到持久化實(shí)例中,標(biāo)識(shí)符的填入可能被推遲到flush的時(shí)間;② persist()方法保證當(dāng)它在一個(gè)事務(wù)外部被調(diào)用的時(shí)候并不觸發(fā)一個(gè)INSERT語(yǔ)句,當(dāng)需要封裝一個(gè)長(zhǎng)會(huì)話流程的時(shí)候,persist()方法是很有必要的;③ save()方法不保證第②條,它要返回標(biāo)識(shí)符,所以它會(huì)立即執(zhí)行INSERT語(yǔ)句,不管是在事務(wù)內(nèi)部還是外部。至于lock()方法和update()方法的區(qū)別,update()方法是把一個(gè)已經(jīng)更改過(guò)的脫管狀態(tài)的對(duì)象變成持久狀態(tài);lock()方法是把一個(gè)沒(méi)有更改過(guò)的脫管狀態(tài)的對(duì)象變成持久狀態(tài)。
131、闡述Session加載實(shí)體對(duì)象的過(guò)程。
答:Session加載實(shí)體對(duì)象的步驟是:
① Session在調(diào)用數(shù)據(jù)庫(kù)查詢功能之前,首先會(huì)在一級(jí)緩存中通過(guò)實(shí)體類(lèi)型和主鍵進(jìn)行查找,如果一級(jí)緩存查找命中且數(shù)據(jù)狀態(tài)合法,則直接返回;
② 如果一級(jí)緩存沒(méi)有命中,接下來(lái)Session會(huì)在當(dāng)前NonExists記錄(相當(dāng)于一個(gè)查詢黑名單,如果出現(xiàn)重復(fù)的無(wú)效查詢可以迅速做出判斷,從而提升性能)中進(jìn)行查找,如果NonExists中存在同樣的查詢條件,則返回null;
③ 如果一級(jí)緩存查詢失敗則查詢二級(jí)緩存,如果二級(jí)緩存命中則直接返回;
④ 如果之前的查詢都未命中,則發(fā)出SQL語(yǔ)句,如果查詢未發(fā)現(xiàn)對(duì)應(yīng)記錄則將此次查詢添加到Session的NonExists中加以記錄,并返回null;
⑤ 根據(jù)映射配置和SQL語(yǔ)句得到ResultSet,并創(chuàng)建對(duì)應(yīng)的實(shí)體對(duì)象;
⑥ 將對(duì)象納入Session(一級(jí)緩存)的管理;
⑦ 如果有對(duì)應(yīng)的攔截器,則執(zhí)行攔截器的onLoad方法;
⑧ 如果開(kāi)啟并設(shè)置了要使用二級(jí)緩存,則將數(shù)據(jù)對(duì)象納入二級(jí)緩存;
⑨ 返回?cái)?shù)據(jù)對(duì)象。
132、Query接口的list方法和iterate方法有什么區(qū)別?
答:
① list()方法無(wú)法利用一級(jí)緩存和二級(jí)緩存(對(duì)緩存只寫(xiě)不讀),它只能在開(kāi)啟查詢緩存的前提下使用查詢緩存;iterate()方法可以充分利用緩存,如果目標(biāo)數(shù)據(jù)只讀或者讀取頻繁,使用iterate()方法可以減少性能開(kāi)銷(xiāo)。
② list()方法不會(huì)引起N+1查詢問(wèn)題,而iterate()方法可能引起N+1查詢問(wèn)題
說(shuō)明:關(guān)于N+1查詢問(wèn)題,可以參考CSDN上的一篇文章《什么是N+1查詢》
133、Hibernate如何實(shí)現(xiàn)分頁(yè)查詢?
答:通過(guò)Hibernate實(shí)現(xiàn)分頁(yè)查詢,開(kāi)發(fā)人員只需要提供HQL語(yǔ)句(調(diào)用Session的createQuery()方法)或查詢條件(調(diào)用Session的createCriteria()方法)、設(shè)置查詢起始行數(shù)(調(diào)用Query或Criteria接口的setFirstResult()方法)和最大查詢行數(shù)(調(diào)用Query或Criteria接口的setMaxResults()方法),并調(diào)用Query或Criteria接口的list()方法,Hibernate會(huì)自動(dòng)生成分頁(yè)查詢的SQL語(yǔ)句。
134、鎖機(jī)制有什么用?簡(jiǎn)述Hibernate的悲觀鎖和樂(lè)觀鎖機(jī)制。
答:有些業(yè)務(wù)邏輯在執(zhí)行過(guò)程中要求對(duì)數(shù)據(jù)進(jìn)行排他性的訪問(wèn),于是需要通過(guò)一些機(jī)制保證在此過(guò)程中數(shù)據(jù)被鎖住不會(huì)被外界修改,這就是所謂的鎖機(jī)制。
Hibernate支持悲觀鎖和樂(lè)觀鎖兩種鎖機(jī)制。悲觀鎖,顧名思義悲觀的認(rèn)為在數(shù)據(jù)處理過(guò)程中極有可能存在修改數(shù)據(jù)的并發(fā)事務(wù)(包括本系統(tǒng)的其他事務(wù)或來(lái)自外部系統(tǒng)的事務(wù)),于是將處理的數(shù)據(jù)設(shè)置為鎖定狀態(tài)。悲觀鎖必須依賴數(shù)據(jù)庫(kù)本身的鎖機(jī)制才能真正保證數(shù)據(jù)訪問(wèn)的排他性,關(guān)于數(shù)據(jù)庫(kù)的鎖機(jī)制和事務(wù)隔離級(jí)別在《Java面試題大全(上)》中已經(jīng)討論過(guò)了。樂(lè)觀鎖,顧名思義,對(duì)并發(fā)事務(wù)持樂(lè)觀態(tài)度(認(rèn)為對(duì)數(shù)據(jù)的并發(fā)操作不會(huì)經(jīng)常性的發(fā)生),通過(guò)更加寬松的鎖機(jī)制來(lái)解決由于悲觀鎖排他性的數(shù)據(jù)訪問(wèn)對(duì)系統(tǒng)性能造成的嚴(yán)重影響。最常見(jiàn)的樂(lè)觀鎖是通過(guò)數(shù)據(jù)版本標(biāo)識(shí)來(lái)實(shí)現(xiàn)的,讀取數(shù)據(jù)時(shí)獲得數(shù)據(jù)的版本號(hào),更新數(shù)據(jù)時(shí)將此版本號(hào)加1,然后和數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本號(hào)進(jìn)行比較,如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)庫(kù)中此記錄的當(dāng)前版本號(hào)則更新數(shù)據(jù),否則認(rèn)為是過(guò)期數(shù)據(jù)無(wú)法更新。Hibernate中通過(guò)Session的get()和load()方法從數(shù)據(jù)庫(kù)中加載對(duì)象時(shí)可以通過(guò)參數(shù)指定使用悲觀鎖;而樂(lè)觀鎖可以通過(guò)給實(shí)體類(lèi)加整型的版本字段再通過(guò)XML或@Version注解進(jìn)行配置。
提示:使用樂(lè)觀鎖會(huì)增加了一個(gè)版本字段,很明顯這需要額外的空間來(lái)存儲(chǔ)這個(gè)版本字段,浪費(fèi)了空間,但是樂(lè)觀鎖會(huì)讓系統(tǒng)具有更好的并發(fā)性,這是對(duì)時(shí)間的節(jié)省。因此樂(lè)觀鎖也是典型的空間換時(shí)間的策略。
135、闡述實(shí)體對(duì)象的三種狀態(tài)以及轉(zhuǎn)換關(guān)系。
答:最新的Hibernate文檔中為Hibernate對(duì)象定義了四種狀態(tài)(原來(lái)是三種狀態(tài),面試的時(shí)候基本上問(wèn)的也是三種狀態(tài)),分別是:瞬時(shí)態(tài)(new, or transient)、持久態(tài)(managed, or persistent)、游狀態(tài)(detached)和移除態(tài)(removed,以前Hibernate文檔中定義的三種狀態(tài)中沒(méi)有移除態(tài)),如下圖所示,就以前的Hibernate文檔中移除態(tài)被視為是瞬時(shí)態(tài)。

瞬時(shí)態(tài):當(dāng)new一個(gè)實(shí)體對(duì)象后,這個(gè)對(duì)象處于瞬時(shí)態(tài),即這個(gè)對(duì)象只是一個(gè)保存臨時(shí)數(shù)據(jù)的內(nèi)存區(qū)域,如果沒(méi)有變量引用這個(gè)對(duì)象,則會(huì)被JVM的垃圾回收機(jī)制回收。這個(gè)對(duì)象所保存的數(shù)據(jù)與數(shù)據(jù)庫(kù)沒(méi)有任何關(guān)系,除非通過(guò)Session的save()、saveOrUpdate()、persist()、merge()方法把瞬時(shí)態(tài)對(duì)象與數(shù)據(jù)庫(kù)關(guān)聯(lián),并把數(shù)據(jù)插入或者更新到數(shù)據(jù)庫(kù),這個(gè)對(duì)象才轉(zhuǎn)換為持久態(tài)對(duì)象。
持久態(tài):持久態(tài)對(duì)象的實(shí)例在數(shù)據(jù)庫(kù)中有對(duì)應(yīng)的記錄,并擁有一個(gè)持久化標(biāo)識(shí)(ID)。對(duì)持久態(tài)對(duì)象進(jìn)行delete操作后,數(shù)據(jù)庫(kù)中對(duì)應(yīng)的記錄將被刪除,那么持久態(tài)對(duì)象與數(shù)據(jù)庫(kù)記錄不再存在對(duì)應(yīng)關(guān)系,持久態(tài)對(duì)象變成移除態(tài)(可以視為瞬時(shí)態(tài))。持久態(tài)對(duì)象被修改變更后,不會(huì)馬上同步到數(shù)據(jù)庫(kù),直到數(shù)據(jù)庫(kù)事務(wù)提交。
游離態(tài):當(dāng)Session進(jìn)行了close()、clear()、evict()或flush()后,實(shí)體對(duì)象從持久態(tài)變成游離態(tài),對(duì)象雖然擁有持久和與數(shù)據(jù)庫(kù)對(duì)應(yīng)記錄一致的標(biāo)識(shí)值,但是因?yàn)閷?duì)象已經(jīng)從會(huì)話中清除掉,對(duì)象不在持久化管理之內(nèi),所以處于游離態(tài)(也叫脫管態(tài))。游離態(tài)的對(duì)象與臨時(shí)狀態(tài)對(duì)象是十分相似的,只是它還含有持久化標(biāo)識(shí)。
提示:關(guān)于這個(gè)問(wèn)題,在Hibernate的官方文檔中有更為詳細(xì)的解讀。
136、如何理解Hibernate的延遲加載機(jī)制?在實(shí)際應(yīng)用中,延遲加載與Session關(guān)閉的矛盾是如何處理的?
答:延遲加載就是并不是在讀取的時(shí)候就把數(shù)據(jù)加載進(jìn)來(lái),而是等到使用時(shí)再加載。Hibernate使用了虛擬代理機(jī)制實(shí)現(xiàn)延遲加載,我們使用Session的load()方法加載數(shù)據(jù)或者一對(duì)多關(guān)聯(lián)映射在使用延遲加載的情況下從一的一方加載多的一方,得到的都是虛擬代理,簡(jiǎn)單的說(shuō)返回給用戶的并不是實(shí)體本身,而是實(shí)體對(duì)象的代理。代理對(duì)象在用戶調(diào)用getter方法時(shí)才會(huì)去數(shù)據(jù)庫(kù)加載數(shù)據(jù)。但加載數(shù)據(jù)就需要數(shù)據(jù)庫(kù)連接。而當(dāng)我們把會(huì)話關(guān)閉時(shí),數(shù)據(jù)庫(kù)連接就同時(shí)關(guān)閉了。
延遲加載與session關(guān)閉的矛盾一般可以這樣處理:
① 關(guān)閉延遲加載特性。這種方式操作起來(lái)比較簡(jiǎn)單,因?yàn)镠ibernate的延遲加載特性是可以通過(guò)映射文件或者注解進(jìn)行配置的,但這種解決方案存在明顯的缺陷。首先,出現(xiàn)"no session or session was closed"通常說(shuō)明系統(tǒng)中已經(jīng)存在主外鍵關(guān)聯(lián),如果去掉延遲加載的話,每次查詢的開(kāi)銷(xiāo)都會(huì)變得很大。
② 在session關(guān)閉之前先獲取需要查詢的數(shù)據(jù),可以使用工具方法Hibernate.isInitialized()判斷對(duì)象是否被加載,如果沒(méi)有被加載則可以使用Hibernate.initialize()方法加載對(duì)象。
③ 使用攔截器或過(guò)濾器延長(zhǎng)Session的生命周期直到視圖獲得數(shù)據(jù)。Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterceptor就是這種做法。
137、舉一個(gè)多對(duì)多關(guān)聯(lián)的例子,并說(shuō)明如何實(shí)現(xiàn)多對(duì)多關(guān)聯(lián)映射。
答:例如:商品和訂單、學(xué)生和課程都是典型的多對(duì)多關(guān)系??梢栽趯?shí)體類(lèi)上通過(guò)@ManyToMany注解配置多對(duì)多關(guān)聯(lián)或者通過(guò)映射文件中的和標(biāo)簽配置多對(duì)多關(guān)聯(lián),但是實(shí)際項(xiàng)目開(kāi)發(fā)中,很多時(shí)候都是將多對(duì)多關(guān)聯(lián)映射轉(zhuǎn)換成兩個(gè)多對(duì)一關(guān)聯(lián)映射來(lái)實(shí)現(xiàn)的。
138、談一下你對(duì)繼承映射的理解。
答:繼承關(guān)系的映射策略有三種:
① 每個(gè)繼承結(jié)構(gòu)一張表(table per class hierarchy),不管多少個(gè)子類(lèi)都用一張表。
② 每個(gè)子類(lèi)一張表(table per subclass),公共信息放一張表,特有信息放單獨(dú)的表。
③ 每個(gè)具體類(lèi)一張表(table per concrete class),有多少個(gè)子類(lèi)就有多少?gòu)埍怼?br>
第一種方式屬于單表策略,其優(yōu)點(diǎn)在于查詢子類(lèi)對(duì)象的時(shí)候無(wú)需表連接,查詢速度快,適合多態(tài)查詢;缺點(diǎn)是可能導(dǎo)致表很大。后兩種方式屬于多表策略,其優(yōu)點(diǎn)在于數(shù)據(jù)存儲(chǔ)緊湊,其缺點(diǎn)是需要進(jìn)行連接查詢,不適合多態(tài)查詢。
139、簡(jiǎn)述Hibernate常見(jiàn)優(yōu)化策略。
答:這個(gè)問(wèn)題應(yīng)當(dāng)挑自己使用過(guò)的優(yōu)化策略回答,常用的有:
① 制定合理的緩存策略(二級(jí)緩存、查詢緩存)。
② 采用合理的Session管理機(jī)制。
③ 盡量使用延遲加載特性。
④ 設(shè)定合理的批處理參數(shù)。
⑤ 如果可以,選用UUID作為主鍵生成器。
⑥ 如果可以,選用基于版本號(hào)的樂(lè)觀鎖替代悲觀鎖。
⑦ 在開(kāi)發(fā)過(guò)程中, 開(kāi)啟hibernate.show_sql選項(xiàng)查看生成的SQL,從而了解底層的狀況;開(kāi)發(fā)完成后關(guān)閉此選項(xiàng)。
⑧ 考慮數(shù)據(jù)庫(kù)本身的優(yōu)化,合理的索引、恰當(dāng)?shù)臄?shù)據(jù)分區(qū)策略等都會(huì)對(duì)持久層的性能帶來(lái)可觀的提升,但這些需要專業(yè)的DBA(數(shù)據(jù)庫(kù)管理員)提供支持。
140、談一談Hibernate的一級(jí)緩存、二級(jí)緩存和查詢緩存。
答:Hibernate的Session提供了一級(jí)緩存的功能,默認(rèn)總是有效的,當(dāng)應(yīng)用程序保存持久化實(shí)體、修改持久化實(shí)體時(shí),Session并不會(huì)立即把這種改變提交到數(shù)據(jù)庫(kù),而是緩存在當(dāng)前的Session中,除非顯示調(diào)用了Session的flush()方法或通過(guò)close()方法關(guān)閉Session。通過(guò)一級(jí)緩存,可以減少程序與數(shù)據(jù)庫(kù)的交互,從而提高數(shù)據(jù)庫(kù)訪問(wèn)性能。
SessionFactory級(jí)別的二級(jí)緩存是全局性的,所有的Session可以共享這個(gè)二級(jí)緩存。不過(guò)二級(jí)緩存默認(rèn)是關(guān)閉的,需要顯示開(kāi)啟并指定需要使用哪種二級(jí)緩存實(shí)現(xiàn)類(lèi)(可以使用第三方提供的實(shí)現(xiàn))。一旦開(kāi)啟了二級(jí)緩存并設(shè)置了需要使用二級(jí)緩存的實(shí)體類(lèi),SessionFactory就會(huì)緩存訪問(wèn)過(guò)的該實(shí)體類(lèi)的每個(gè)對(duì)象,除非緩存的數(shù)據(jù)超出了指定的緩存空間。
一級(jí)緩存和二級(jí)緩存都是對(duì)整個(gè)實(shí)體進(jìn)行緩存,不會(huì)緩存普通屬性,如果希望對(duì)普通屬性進(jìn)行緩存,可以使用查詢緩存。查詢緩存是將HQL或SQL語(yǔ)句以及它們的查詢結(jié)果作為鍵值對(duì)進(jìn)行緩存,對(duì)于同樣的查詢可以直接從緩存中獲取數(shù)據(jù)。查詢緩存默認(rèn)也是關(guān)閉的,需要顯示開(kāi)啟。