Hibernate知識點合集(轉載)

一. 簡答題
1. 請說出Hibernate中持久化對象的生命週期以及各種狀態直接的區別,並描述相互之間是如何轉換的。
Hibernate中持久化對象的生命週期有臨時態、持久態和遊離態三種。
處於臨時態的對象主鍵值爲空,並且未與session關聯,數據未保存到數據庫中
處於持久態的對象與session關聯起來,持久化後對象中的數據被保存到數據庫中,並且主鍵值按照.hbm.xml文件中配置的生成方式生成相應的值
處於遊離態的對象脫離了session的管理,是持久化後的一種狀態,主鍵值按照.hbm.xml文件中配置的生成方式生成相應的值
當new一個新的對象時,該對象處於臨時態
當該對象被當作session的參數使用的時候,該對象處於持久態
事務提交,session關閉後,該對象處於遊離態
2.hibernate與數據庫連接的實現?並解釋了一下,例如文件是通過流來實現的!hibernate與數據庫連接是通過什麼實現的?
Hibernate與數據庫的連接是通過JDBC實現的
3.spring和hibernate的事務管理方式有什麼不同?
hibernate的事務管理方式僅僅就是託管給JDBC(如果用JTA那麼就是JTA),而JDBC的一切行爲包括事務是基於一個connection的,那麼hibernate委託給JDBC的事務也就是基於一個session。JTA與JDBC事務不同在於可以跨連接。
spring也是調用hibernate中事務管理的API。hibernate的事務管理,一般是編程性的。而委託給spring之後,可以使用聲明式的,也就是可以在XML之中配置哪些需要進行事務管理,哪些不需要
4.用hibernate的session時要注意幾點
1.在更新數據時,要用open()
2.使用完之後,要close(),這樣連接池會回收該連接。
5.說說在hibernate中使用Integer做映射和使用int做映射之間有什麼差別
使用int做映射,hibernate會自動把int類型轉換爲Integer類型,以便統一以對象方式處理數據。使用Integer就無須轉換。
在從數據庫中取數據的時候,如果是用Integer做的映射,則要求PO對象中對應的類型也必須爲Integer類型,使用的時候需要轉換爲int。如果是int型,則無須轉換。
6.一個網站應用,請設計一個持久化類User,他可能有多張會員卡號、需要多個email地址(數量不定)作爲其身份驗證的方式
設計三個類。User類、會員卡類和email類。User類與會員卡類和email類之間是一對多的關係
7.請簡單評價該設計的優劣:身份證號碼作爲一個person表的主鍵
一個表的主鍵值設計最好不要採用具有業務含義的字段。理由有二:
1.具有業務含義的字段的長度不固定
2.具有業務含義的字段的取值範圍不定。可能是純數字,也可能是純字符,或者是數字和字符的混合情況。
上述兩個方面一但發生變動將不利於業務層的處理。
8.Hibernate如何獲取指定主鍵id的某對象,請舉例,並進行可能的優劣比較
三種方式:get(),load()和find()
Get()和load()是先在緩存中查找對象,如果找不到再去數據庫中查詢;
Find()是無論何時都在數據庫中查詢對象。
三者比較起來Get()和load()的性能稍好一點。
二.問答題
1.請說出Hibernate中的映射關係有幾種,分別是什麼,如何配置
Hibernate中的映射關係有一對一、一對多、多對多三種。
一對一關係比較簡單,只需在主控方(由誰想得到誰,前者即是主控方)定義。配置如下:
簡單模式:
<one-to-one name=”” class=”” cascade=”” outer-join=”” constrained=”” />
完整模式:
<one-to-one name=”” class=”” cascade=”” outer-join=”” constrained=”” property-ref=”” access=”” />
解釋:
屬性 描述 類型 必須
name 與PO中對應的和主控方有一對一關聯的屬性名稱,必須一致 TEXT N
class 與PO中對應的和主控方有一對一關聯的屬性類型,要求必須寫出完整全類路徑 TEXT N
cascade 針對被控方操作的級聯關係,由主控方觸發。它指的是當主控方執行操作時,被控方是否執行同一操作。
可選值:
All:所有情況下均觸發級聯操作
None:與All相反
Save-update:在執行save-update時進行級聯操作
Delete:在執行delete時進行級聯操作 TEXT N
outer-join 是否使用外連接:
True:總是使用外連接
False:與true相反
Auto(默認):如果被動方沒有采用代理機制,則使用外連接 BOOL N
constrained 約束。它表示主控方表的主鍵上是否存在被控方的外鍵對其進行約束。它決定了save、delete等方法的級聯操作順序 TEXT N
property-ref 被控類中用於和主控類相關聯的屬性名稱。默認爲關聯類的主鍵屬性名稱。一般我們通過主鍵建立一對一的關聯,所以採用默認值即可。如果一對一的關聯並非建立在主鍵之間,則可通過此參數指定關聯屬性 TEXT N
access 屬性值的讀取方式:
Field:通過java反射機制來訪問實體的屬性
Property(默認):通過getter()和setter()方法訪問實體的屬性
ClassName:指定實現net.sf.hibernate.property.PropertyAccessor接口的全路徑類名,通過該類中指定的方式訪問實體屬性 TEXT N
一對多關係分爲單向一對多關係和雙向一對多關係。
單向一對多關係只需在“一”方進行配置,雙向一對多需要在關聯雙方均加以配置。配置如下:
單向一對多:
<set name=”” table=”” lazy=”” inverse=”false” cascade=”” sort=”” order-by=”” >
<key column=”” />
<one-to-many class=”” />
</set>
雙向一對多:
一的一方:
<set name=”” table=”” lazy=”” inverse=”true” cascade=”” sort=”” order-by=”” >
<key column=”” />
<one-to-many class=”” />
</set>
多的一方:
<many-to-one name=”” class=”” cascade=”” outer-join=”” update=”” insert=”” access=”” column=”” not-null=”” />
被動方的記錄由Hibernate負責讀取,之後存放在主控方指定的Collection類型屬性中。
解釋:
屬性 描述 類型 必須
name 與PO中對應的和主控方有一對多關聯的集合屬性名稱,必須一致 TEXT Y
column 關聯字段名 TEXT Y
class 一的一方的全路徑類名 TEXT N
cascade 針對被控方操作的級聯關係,由主控方觸發。它指的是當主控方執行操作時,被控方是否執行同一操作。
可選值:
All:所有情況下均觸發級聯操作
None:與All相反
Save-update:在執行save-update時進行級聯操作
Delete:在執行delete時進行級聯操作 TEXT N
update 是否對關聯字段進行update操作。默認爲true BOOL N
insert 是否對關聯字段進行insert操作。默認爲true BOOL N
Outer-join 是否使用外連接:
True:總是使用外連接
False:與true相反
Auto(默認):如果被動方沒有采用代理機制,則使用外連接 TEXT N
Property-ref 被控類中用於和主控類相關聯的屬性名稱。默認爲關聯類的主鍵屬性名稱。一般我們通過主鍵建立一對一的關聯,所以採用默認值即可。如果一對一的關聯並非建立在主鍵之間,則可通過此參數指定關聯屬性 TEXT N
access 屬性值的讀取方式:
Field:通過java反射機制來訪問實體的屬性
Property(默認):通過getter()和setter()方法訪問實體的屬性
ClassName:指定實現net.sf.hibernate.property.PropertyAccessor接口的全路徑類名,通過該類中指定的方式訪問實體屬性 TEXT N
多對多關聯:由於多對多關聯的性能不佳,在設計中應避免大量使用。應根據情況,採取延遲加載機制來避免無謂的性能開銷。配置如下:
<set name=”” table=”” lazy=”” inverse=”” cascade=”” sort=””>
<key column=”” />
<many-to-many class=”” column=”” outer-join=””/>
</set>
解釋:
屬性 描述 類型 必須
column 中間表映射中,關聯方在中間表的關聯字段 TEXT Y
class 關聯放的類全路徑名稱 TEXT Y
Outer-join 是否使用外連接:
True:總是使用外連接
False:與true相反
Auto(默認):如果被動方沒有采用代理機制,則使用外連接 TEXT N
2. 請描述對象建模時的繼承關係在Hibernate中有幾種映射方式,如何映射
一共有三種:
每顆類繼承樹使用一張表,配置如下:
<class name=" " table=" ">
      <discriminator column="subtype" type="string" />
      <subclass name="" discriminator-value=" ">
            <property name="">
      <column name="" sql-type="" />
</property>
      </subclass>
 </class>
三個類對應的字段都在一個數據表裏表示。subtype字段標識存儲的是哪個子類,與xml文件中的
<discriminator column="subtype" type="string" />對應。
每個子類各一張表,配置如下:
<class name=" " table=" ">
      <joined-subclass name=" " table=" ">
            <key column=" "/>
            <property name=" ">
     <column name=" " sql-type=" "/>
            </property>
      </joined-subclass>
</class>
每個具體類各一張表,配置如下:
<class name=" " table=“">  
        <id name=" " type=" " unsaved-value=" " >
        </id>
        <property name=" ">
  <column name=" " sql-type=" "/>
        </property>
</class>
3. 請描述Hibernate中的緩存機制
緩存是介於應用程序和物理數據源之間,其作用是爲了降低應用程序對物理數據源訪問的頻次,從而提高了應用的運行性能。緩存內的數據是對物理數據源中的數據的複製,應用程序在運行時從緩存讀寫數據,在特定的時刻或事件會同步緩存和物理數據源的數據。 
緩存的介質一般是內存,所以讀寫速度很快。但如果緩存中存放的數據量非常大時,也會用硬盤作爲緩存介質。緩存的實現不僅僅要考慮存儲的介質,還要考慮到管理緩存的併發訪問和緩存數據的生命週期。
Hibernate的緩存包括Session的緩存和SessionFactory的緩存,其中SessionFactory的緩存又可以分爲兩類:內置緩存和外置緩存。Session的緩存是內置的,不能被卸載,也被稱爲Hibernate的第一級緩存。Session的緩存是指Session的一些集合屬性包含的數據。SessionFactory的內置緩存中存放了映射元數據和預定義SQL語句,映射元數據是映射文件中數據的拷貝,而預定義SQL語句是在Hibernate初始化階段根據映射元數據推導出來,SessionFactory的內置緩存是隻讀的,應用程序不能修改緩存中的映射元數據和預定義SQL語句,因此SessionFactory不需要進行內置緩存與映射文件的同步。SessionFactory的外置緩存是一個可配置的插件。在默認情況下,SessionFactory不會啓用這個插件。外置緩存的數據是數據庫數據的拷貝,外置緩存的介質可以是內存或者硬盤。SessionFactory的外置緩存也被稱爲Hibernate的第二級緩存。
Hibernate的這兩級緩存都位於持久化層,存放的都是數據庫數據的拷貝,那麼它們之間的區別是什麼呢?爲了理解二者的區別,需要深入理解持久化層的緩存的兩個特性:緩存的範圍和緩存的併發訪問策略。
持久化層的緩存的範圍
緩存的範圍決定了緩存的生命週期以及可以被誰訪問。緩存的範圍分爲三類。
1 事務範圍:緩存只能被當前事務訪問。緩存的生命週期依賴於事務的生命週期,當事務結束時,緩存也就結束生命週期。在此範圍下,緩存的介質是內存。事務可以是數據庫事務或者應用事務,每個事務都有獨自的緩存,緩存內的數據通常採用相互關聯的的對象形式。
2 進程範圍:緩存被進程內的所有事務共享。這些事務有可能是併發訪問緩存,因此必須對緩存採取必要的事務隔離機制。緩存的生命週期依賴於進程的生命週期,進程結束時,緩存也就結束了生命週期。進程範圍的緩存可能會存放大量的數據,所以存放的介質可以是內存或硬盤。緩存內的數據既可以是相互關聯的對象形式也可以是對象的鬆散數據形式。鬆散的對象數據形式有點類似於對象的序列化數據,但是對象分解爲鬆散的算法比對象序列化的算法要求更快。
3 集羣範圍:在集羣環境中,緩存被一個機器或者多個機器的進程共享。緩存中的數據被複制到集羣環境中的每個進程節點,進程間通過遠程通信來保證緩存中的數據的一致性,緩存中的數據通常採用對象的鬆散數據形式。
對大多數應用來說,應該慎重地考慮是否需要使用集羣範圍的緩存,因爲訪問的速度不一定會比直接訪問數據庫數據的速度快多少。
持久化層可以提供多種範圍的緩存。如果在事務範圍的緩存中沒有查到相應的數據,還可以到進程範圍或集羣範圍的緩存內查詢,如果還是沒有查到,那麼只有到數據庫中查詢。事務範圍的緩存是持久化層的第一級緩存,通常它是必需的;進程範圍或集羣範圍的緩存是持久化層的第二級緩存,通常是可選的。
持久化層的緩存的併發訪問策略
當多個併發的事務同時訪問持久化層的緩存的相同數據時,會引起併發問題,必須採用必要的事務隔離措施。
在進程範圍或集羣範圍的緩存,即第二級緩存,會出現併發問題。因此可以設定以下四種類型的併發訪問策略,每一種策略對應一種事務隔離級別。
事務型:僅僅在受管理環境中適用。它提供了Repeatable Read事務隔離級別。對於經常被讀但很少修改的數據,可以採用這種隔離類型,因爲它可以防止髒讀和不可重複讀這類的併發問題。
讀寫型:提供了Read Committed事務隔離級別。僅僅在非集羣的環境中適用。對於經常被讀但很少修改的數據,可以採用這種隔離類型,因爲它可以防止髒讀這類的併發問題。
非嚴格讀寫型:不保證緩存與數據庫中數據的一致性。如果存在兩個事務同時訪問緩存中相同數據的可能,必須爲該數據配置一個很短的數據過期時間,從而儘量避免髒讀。對於極少被修改,並且允許偶爾髒讀的數據,可以採用這種併發訪問策略。
只讀型:對於從來不會修改的數據,如參考數據,可以使用這種併發訪問策略。
事務型併發訪問策略是事務隔離級別最高,只讀型的隔離級別最低。事務隔離級別越高,併發性能就越低。
什麼樣的數據適合存放到第二級緩存中?
1、很少被修改的數據 
2、不是很重要的數據,允許出現偶爾併發的數據
3、不會被併發訪問的數據
4、參考數據
不適合存放到第二級緩存的數據?
1、經常被修改的數據
2、財務數據,絕對不允許出現併發
3、與其他應用共享的數據。
Hibernate的二級緩存
如前所述,Hibernate提供了兩級緩存,第一級是Session的緩存。由於Session對象的生命週期通常對應一個數據庫事務或者一個應用事務,因此它的緩存是事務範圍的緩存。第一級緩存是必需的,不允許而且事實上也無法卸除。在第一級緩存中,持久化類的每個實例都具有唯一的OID。
第二級緩存是一個可插拔的的緩存插件,它是由SessionFactory負責管理。由於SessionFactory對象的生命週期和應用程序的整個過程對應,因此第二級緩存是進程範圍或者集羣範圍的緩存。這個緩存中存放的對象的鬆散數據。第二級對象有可能出現併發問題,因此需要採用適當的併發訪問策略,該策略爲被緩存的數據提供了事務隔離級別。緩存適配器用於把具體的緩存實現軟件與Hibernate集成。第二級緩存是可選的,可以在每個類或每個集合的粒度上配置第二級緩存。
Hibernate的二級緩存策略的一般過程如下:
1) 條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有字段)這樣的SQL語句查詢數據庫,一次獲得所有的數據對象。 
2) 把獲得的所有數據對象根據ID放入到第二級緩存中。 
3) 當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那麼從二級緩存中查;查不到,再查詢數據庫,把結果按照ID放入到緩存。 
4) 刪除、更新、增加數據的時候,同時更新緩存。
Hibernate的二級緩存策略,是針對於ID查詢的緩存策略,對於條件查詢則毫無作用。爲此,Hibernate提供了針對條件查詢的Query緩存。
Hibernate的Query緩存策略的過程如下: 
1) Hibernate首先根據這些信息組成一個Query Key,Query Key包括條件查詢的請求一般信息:SQL, SQL需要的參數,記錄範圍(起始位置rowStart,最大記錄個數maxRows),等。 
2) Hibernate根據這個Query Key到Query緩存中查找對應的結果列表。如果存在,那麼返回這個結果列表;如果不存在,查詢數據庫,獲取結果列表,把整個結果列表根據Query Key放入到Query緩存中。 
3) Query Key中的SQL涉及到一些表名,如果這些表的任何數據發生修改、刪除、增加等操作,這些相關的Query Key都要從緩存中清空。
三.程序分析
1.一個WEB程序,首先,頁面註冊一個用戶比如用戶名 aa 密碼 aa。註冊完以後,查看數據庫,數據插入到了數據庫中,
然後重開個頁面,登錄,輸入用戶名 aa 密碼 aa,無法登錄,說是找不到。其調用的方法是 getUserByNameAndPassword(用戶名,密碼)。此時服務器不關,直接執行JUnit的測試文件,調用該方法,能找到這個用戶的註冊信息, ,然後服務器重啓,此時再輸入用戶名 aa 密碼 aa,便能登錄了,請問下,在不看代碼的情況下,可能是什麼地方出了問題?插入及訪問代碼是基於Hibernate 編寫的,要求寫出可能的情況及解決方案
第一種方案:應該是hibernate緩存的問題.在註冊完以後只是把數據保存在了緩存裏面,而沒有提交到數據庫.當你用Junit測試的時候當然可以測成功,因爲hibernate是先查看緩存的.如果緩存裏面有它想要的東西就不查數據庫了,直接拿過來用.如果沒有才查的.至於說關閉服務器以後,重起就可以登陸了.那應該是在關閉服務器的同時,hibernate   commit了緩存裏面的數據.


第二種方案:getUserByNameAndPassword(用戶名,密碼)方法得不到用戶很可能是hibernate的緩存機制沒有控制好,導致該方法讀取用戶驗證時並不是從數據庫讀取,而是從hibernate的session中讀取,session由於還是原先沒插值前的緩存,所以得不到用戶。有2中解決方法:1.在getUserByNameAndPassword(用戶名,密碼)方法中加上HibernateSessionFactory.getSession().clear();2.在session.save()方法裏面(也就是insert)在插入了註冊的用戶信息,事務提交後,調用session.close()方法將session關閉。
    
第三種方案:在hibernate進行save操作的時候,它會將save的這條數據同時緩存進session和sessionFactory(如果有配二級緩存的話)。當下次來查詢的時候,Hibernate會先從查詢sessionFactory,如果沒有查到,繼續查詢session,如果還是沒有查詢到,就查詢數據庫。但現在的現象好像是,hibernate查詢了session沒有查到之後,就沒有繼續進行查詢了,而是就返回結果了。find操作和save操作應該是不會共享session的,因爲session是非線程安全的。可能是在二級緩存的時候出了問題,在二級緩存中好像有一個類似“黑名單”的東西,裏面保存了沒有記錄的查詢語句,當hibernate發行這條查詢語句在這個“黑名單”中的時候,它就不會繼續查詢數據庫了,而是直接返回沒有找到數據。


第四種方案:其實這個應該是緩存問題的一種錯誤使用方式造成的。他應該是在getUserByNameAndPassword裏用的get()或者load()這種方法去獲取的數據。這2種方法都是從緩存裏去讀取數據。只有find()是直接從數據庫拿數據。而他的數據庫的連接方式可能是註冊時開啓了一個連接,之後並未馬上關閉,之後登陸時用的同一個連接,所以是不會從數據庫拿數據的。重起服務器之後,是因爲連接裏的數據更新了,所以是可以得到數據的。解決方式可以有好幾種了。將獲得數據改成每次都從數據庫拿的方式,或者是上面說的將session裏的流清空掉,還可以再開起一個連接。你可以根據需要來決定。至於配置,可以不需要做高級的屬性設置的。補充一下,Junit測試是因爲它每次連接都是新的。


第五種方案:它應該是啓用了hibernate二級緩存,而且還使用了查詢緩存,在它的createQuery("from   User   u   where   u.userName=?   and   password=?   ")語句後面恐怕還有setCacheable(true)這樣的語句,並且在你創建該用戶前肯定用該用戶和密碼登錄過,此時肯定登錄不了,查詢返回的結果是null,但是已經把該查詢和結果緩存到二級查詢緩存中去了,當你創建該用戶後,不重起登錄,該查詢取的是查詢緩存中的結果,即null,所以登錄不了。而在JUnit測試中,肯定有開關,不使用二級查詢緩存,即不執行setCacheable(true),這樣就直接查數據庫,就能查到了。
2.指出一下代碼哪裏錯誤使用了Hibernate。背景簡介:Board是一個實體類,id是它的主鍵,name和description是他的兩個屬性。BoardDao是Board實體的數據訪問對象,BoardBo是業務對象,用戶提交變更Board對象的請求,由Struts的BoardAction接收,調用BoardBo處理。HibernateUtil.currentSession()用於返回當前請求的Session對象。 
代碼
1.    //數據訪問層代碼:BoardDao.java   
2.    public Board loadBoard(Long id) {   
3.        Session session = HibernateUtil.currentSession();    
4.        return session.load(Board.class, id);   
5.    }   
6.    public void updateBoard(Board board) {   
7.        Session session = HibernateUtil.currentSession();    
8.        session.update(board);   
9.    }   
10.  
11.    //業務對象層代碼:BoardBo.java    
12.    private BoardDao boardDao;   
13.    public void updateBoard(Long id, String name, String description) {   
14.        Board board = boardDao.loadBoard(id);   
15.        board.setName(name);   
16.        board.setDescription(description);   
17.        boardDao.updateBoard(board);   
18.    }   
19.  
20.    //Web控制器代碼:BoardAction.java   
21.    private BoardBo BoardBo;   
22.    public ActionForward execute(   
23. ActionMapping mapping,    
24. ActionForm form,   
25. HttpServletRequest request,    
26. HttpServletResponse response) throws Exception {   
27.        String id = request.getParameter("id");   
28.        String name = request.getParameter("name");   
29.        String description = request.getParameter("description");   
30.        boardBo.updateBoard(id, name, description);   
31.        return mapping.findForward("update-success");   
32.    }   
1.第30行boardBo.updateBoard(id, name, description)沒有對id進行類型轉換。接收時爲String,調用updateBoard時需要的是Long型。
2.持久層的操作沒有關閉session的代碼,並且在update之後沒有commit();
四.判斷題
1.使用save方法persist一個對象時,便立即向數據庫發送執行insert sql語句?
不會。先保存在session緩存中。待commit()之後才向數據庫發送insert sql語句
========================================================================
5.Hibernate有哪幾種查詢數據的方式 
hql查詢,sql查詢,條件查詢


6.load()和get()的區別 
hibernate對於load方法認爲該數據在數據庫中一定存在,可以放心的使用代理來延遲加載,load默認支持延遲加載,在用到對象中的其他屬性數 據時才查詢數據庫,但是萬一數據庫中不存在該記錄,只能拋異常ObjectNotFoundEcception;所說的load方法拋異常是指在使用該對 象的數據時,數據庫中不存在該數據時拋異常,而不是在創建這個對象時。由於session中的緩存對於hibernate來說是個相當廉價的資源,所以在 load時會先查一下session緩存看看該id對應的對象是否存在,不存在則創建代理(load時候之查詢一級緩存,不存在則創建代理)。get() 現在一級緩存找,沒有就去二級緩存找,沒有就去數據庫找,沒有就返回null ;而對於get方法,hibernate一定要獲取到真實的數據,否則返回null。


7.談談hibernate的延遲加載和openSessionInView 
延遲加載要在session範圍內,用到的時候再加載;opensessioninview是在web層寫了一個
filter來打開和關閉session,這樣就表示在一次request過程中session一直開着,保證了延遲
加載在session中的這個前提。


8.spring的事務有幾種方式?談談spring事務的隔離級別和傳播行爲。 
聲明事務和編程事務 
隔離級別: 
- DEFAULT使用數據庫默認的隔離級別 
- READ_UNCOMMITTED會出現髒讀,不可重複讀和幻影讀問題 
- READ_COMMITTED會出現重複讀和幻影讀 
- REPEATABLE_READ會出現幻影讀 
- SERIALIZABLE最安全,但是代價最大,性能影響極其嚴重 
和傳播行: 
- REQUIRED存在事務就融入該事務,不存在就創建事務 
- SUPPORTS存在事務就融入事務,不存在則不創建事務 
- MANDATORY存在事務則融入該事務,不存在,拋異常 
- REQUIRES_NEW總是創建新事務 
- NOT_SUPPORTED存在事務則掛起,一直執行非事務操作 
- NEVER總是執行非事務,如果當前存在事務則拋異常 
- NESTED嵌入式事務


9.Hibernate中的update()和saveOrUpdate()的區別. 
摘自hibernate說明文檔: 
saveOrUpdate()做下面的事: 
如果對象已經在本session中持久化了,不做任何事 
如果另一個與本session關聯的對象擁有相同的持久化標識(identifier),拋出一個異常 
如果對象沒有持久化標識(identifier)屬性,對其調用save() 
如果對象的持久標識(identifier)表明其是一個新實例化的對象,對其調用save() 
如果對象是附帶版本信息的(通過 <version>或 <timestamp>) 並且版本屬性的值表明其是一個新實例化的對象,save()它。 否則update() 這個對象
10.Spring對多種ORM框架提供了很好的支持,簡單描述在Spring中使用Hibernate的方法,並結合事務管理。 
getHiberanteTemplate裏面提供了save,update,delete,find等方法。 
簡單說一個:如果配置了聲明式事務,當執行getHibernateTemplate的各種方法的時候,事務會
自動被加載 
如果沒有配置事務,那麼以上操作不會真正的被同步到數據庫,除非配置了hibernate的
autocommit=true
8.spring的事務有幾種方式?談談spring事務的隔離級別和傳播行爲。 
spring事務分兩種形式,聲明式事務和編程式事務,spring提供了一個事務的接口
PaltformTractionManager接口,針對不同的事務,spring進行了不同的實現,對hibernate事務
的實現HIbernateTractionManager,對JDBC的JdbcTractionManager,
DataSourceTractionManager以及JdoTractionManager。接口platformTractionManager提供了三
個方法,獲取事務,提交和回滾的方法。
******************************************************************************
分享面試題二】Spring,hibernate,struts的面試筆試題(含答案) 
(聲明:這裏不是爲其他商業利益,是爲學習討論使用)
【鄭重聲明】:單純接分將被刪帖,希望大家有自己的感觸 
Hibernate工作原理及爲什麼要用? 
原理: 
1.讀取並解析配置文件 
2.讀取並解析映射信息,創建SessionFactory 
3.打開Sesssion 
4.創建事務Transation 
5.持久化操作 
6.提交事務 
7.關閉Session 
8.關閉SesstionFactory
爲什麼要用: 
1.    對JDBC訪問數據庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重複性代碼。
2.    Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO層的編碼工作
3.    hibernate使用Java反射機制,而不是字節碼增強程序來實現透明性。
4.    hibernate的性能非常好,因爲它是個輕量級框架。映射的靈活性很出色。它支持各種關係數據庫,從一對一到多對多的各種複雜關係。
2. Hibernate是如何延遲加載? 
1. Hibernate2延遲加載實現:a)實體對象 b)集合(Collection)
2. Hibernate3 提供了屬性的延遲加載功能
當Hibernate在查詢數據的時候,數據並沒有存在與內存中,當程序真正對數據的操作時,對象才存在與內存中,就實現了延遲加載,他節省了服務器的內存開銷,從而提高了服務器的性能。
3.Hibernate中怎樣實現類之間的關係?(如:一對多、多對多的關係)
類與類之間的關係主要體現在表與表之間的關係進行操作,它們都市對對象進行操作,我們程序中把所有的表與類都映射在一起,它們通過配置文件中的many-to-one、one-to-many、many-to-many、
4. 說下Hibernate的緩存機制
1. 內部緩存存在Hibernate中又叫一級緩存,屬於應用事物級緩存
2. 二級緩存: 
a) 應用及緩存 
b) 分佈式緩存 
條件:數據不會被第三方修改、數據大小在可接受範圍、數據更新頻率低、同一數據被系統頻繁使用、非關鍵數據 
c) 第三方緩存的實現
5. Hibernate的查詢方式 
Sql、Criteria,object comptosition 
Hql: 
1、 屬性查詢 
2、 參數查詢、命名參數查詢 
3、 關聯查詢 
4、 分頁查詢 
5、 統計函數
6. 如何優化Hibernate? 
1.使用雙向一對多關聯,不使用單向一對多 
2.靈活使用單向一對多關聯 
3.不用一對一,用多對一取代 
4.配置對象緩存,不使用集合緩存 
5.一對多集合使用Bag,多對多集合使用Set 
6. 繼承類使用顯式多態 
7. 表字段要少,表關聯不要怕多,有二級緩存撐腰
================================================================================
1.Hibernate有哪幾種查詢數據的方式 
         (1)導航對象圖查詢 
      (2)OID查詢 
      (3)HQL 
      (4)QBC 
      (5)本地SQL 


2.load()和get()的區別 




load加載方法: 


Java代碼 


Users user = (Users)session.load(Users.class, userId);     
Users user = (Users)session.load(Users.class, userId); 


get加載方法: 


Java代碼 


Users user = (Users)session.get(Users.class, userId);   
Users user = (Users)session.get(Users.class, userId); 






兩加載方法區別: 


區別1:如果數據庫中,沒有userId的對象。如果通過get方法加載,則返回的是一個null;如果通過load加載,則返回一個代理對象,如果後面代碼如果調用user對象的某個屬性(比如user.getPassword())會拋出異常:org.hibernate.ObjectNotFoundException; 


區別2:load支持延遲加載,get不支持延遲加載。 


也就是說: 


Java代碼 


Users user = (Users)session.load(Users.class, userId);   
Users user = (Users)session.load(Users.class, userId); 


這句代碼不會去執行數據庫查詢,只有用到user時纔會去執行數據庫查詢。 


而: 


Java代碼 


Users user = (Users)session.get(Users.class, userId);   
Users user = (Users)session.get(Users.class, userId); 


則立即去執行數據庫查詢。 所以Users user = (Users)session.load(Users.class, userId);不會執行任何sql。 


注意: 


Java代碼 


Users user = (Users)session.load(Users.class, userId);    
System.out.println(user.getId());   
Users user = (Users)session.load(Users.class, userId); 


System.out.println(user.getId()); 


上面這2句代碼,不會去執行數據庫操作。因爲load後會在hibernate的一級緩存裏存放一個map對象,該map的key就是userId的值,但是當你getId()時,它會去一級緩存裏拿map的key值,而不去執行數據庫查詢。所以不會報任何錯。不會執行任何數據庫操作。 






3.   Hibernate工作原理及爲什麼要用? 


原理: 


1.         讀取並解析配置文件 


2.         讀取並解析映射信息,創建SessionFactory 


3.         打開Sesssion 


4.         創建事務Transation 


5.         持久化操作 


6.         提交事務 


7.         關閉Session 


8.         關閉SesstionFactory 






爲什麼要用: 






1. 對JDBC訪問數據庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重複性代碼。 


2. Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO層的編碼工作 


3. hibernate使用Java反射機制,而不是字節碼增強程序來實現透明性。 


4. hibernate的性能非常好,因爲它是個輕量級框架。映射的靈活性很出色。它支持各種關係數據庫,從一對一到多對多的各種複雜關係。 






4.   Hibernate是如何延遲加載? 


1.         Hibernate2延遲加載實現:a)實體對象  b)集合(Collection) 


2.         Hibernate3 提供了屬性的延遲加載功能 


當Hibernate在查詢數據的時候,數據並沒有存在與內存中,當程序真正對數據的操作時,對象才存在與內存中,就實現了延遲加載,他節省了服務器的內存開銷,從而提高了服務器的性能。 


5.   Hibernate中怎樣實現類之間的關係?(如:一對多、多對多的關係) 


類與類之間的關係主要體現在表與表之間的關係進行操作,它們都市對對象進行操作,我們程序中把所有的表與類都映射在一起,它們通過配置文件中的many-to-one、one-to-many、many-to-many、 






5.   說下Hibernate的緩存機制 


1.         內部緩存存在Hibernate中又叫一級緩存,屬於應用事物級緩存 


2.         二級緩存: 


a)         應用及緩存 


b)        分佈式緩存 


條件:數據不會被第三方修改、數據大小在可接受範圍、數據更新頻率低、同一數據被系統頻繁使用、非         關鍵數據 


c)  第三方緩存的實現 






6.   Hibernate的查詢方式 


Sql、Criteria,object comptosition 


Hql: 


1、  屬性查詢 


2、  參數查詢、命名參數查詢 


3、  關聯查詢 


4、  分頁查詢 


5、  統計函數 






7.   如何優化Hibernate? 


1.         使用雙向一對多關聯,不使用單向一對多 


2.         靈活使用單向一對多關聯 


3.         不用一對一,用多對一取代 


4.         配置對象緩存,不使用集合緩存 


5.         一對多集合使用Bag,多對多集合使用Set 


6.         繼承類使用顯式多態 


7.         表字段要少,表關聯不要怕多,有二級緩存撐腰 


=====================Hibernate筆試題============================================ 




(1)一般情況下,關係數據模型與對象模型之間有哪些匹配關係(多選) 
A)表對應類 
B)記錄對應對象 
C)表的字段對應類的屬性 
D)表之間的參考關係對應類之間的依賴關係 


(2)以下關於SessionFactory的說法哪些正確?(多選) 
A)對於每個數據庫事務,應該創建一個SessionFactory對象 
B)一個SessionFactory對象對應一個數據庫存儲源。 
C)SessionFactory是重量級的對象,不應該隨意創建。如果系統中只有一個數據庫存儲源,只需要創建一個。 
D)SessionFactory的load()方法用於加載持久化對象 




(3)Customer類中有一個Set類型的orders屬性,用來存放Order訂單對象,在Customer.hbm.xml文件中,用哪個元素映射orders屬性? 
A)<set> B)<one-to-many> C)<many-to-one> D)<property> 


(4)<set>元素有一個cascade屬性,如果希望Hibernate級聯保存集合中的對象,casecade屬性應該取什麼值?(單選) 
A)none 
B)save 
C)delete 
D)save-update 




(5)以下哪些屬於Session的方法? 
A)load() 
B)save() 
C)delete() 
D)update() 
E)open() 
F)close() 


(6)以下程序的打印結果是什麼?(單選) 


tx = session.beginTransaction(); 
Customer c1=(Customer)session.load(Customer.class,new Long(1)); 
Customer c2=(Customer)session.load(Customer.class,new Long(1)); 
System.out.println(c1==c2); 
tx.commit(); 
session.close(); 


A)運行出錯,拋出異常 
B)打印false 
C)打印true 




(7)以下程序代碼對Customer的name屬性修改了兩次: 
tx = session.beginTransaction(); 
Customer customer=(Customer)session.load(Customer.class, 
                              new Long(1)); 
customer.setName(\"Jack\"); 
customer.setName(\"Mike\"); 
tx.commit(); 


執行以上程序,Hibernate需要向數據庫提交幾條update語句?(單選) 
A)0 B)1 C)2 D)3 




(8)在持久化層,對象分爲哪些狀態?(多選) 
A)臨時狀態 
B)獨立狀態 
C)遊離狀態 
D)持久化狀態 




(9)對於以下程序,Customer對象在第幾行變爲持久化狀態?(單選) 
Customer customer=new Customer(); //line1 
customer.setName(\"Tom\"); //line2 
Session session1=sessionFactory.openSession(); //line3 
Transaction tx1 = session1.beginTransaction(); //line4 
session1.save(customer); //line4 
tx1.commit(); //line5 
session1.close(); //line6 


A) line1 B)line2 C)line3 D)line4 E)line5 F)line6 




(10)對於以下程序,Customer對象在第幾行變爲遊離狀態?(單選) 
Customer customer=new Customer(); //line1 
customer.setName(\"Tom\"); //line2 
Session session1=sessionFactory.openSession(); //line3 
Transaction tx1 = session1.beginTransaction(); //line4 
session1.save(customer); //line4 
tx1.commit(); //line5 
session1.close(); //line6 


A) line1 B)line2 C)line3 D)line4 E)line5 F)line6 


(11)以下哪一種檢索策略利用了外連結查詢?(單選) 
A)立即檢索 B)延遲檢索 C)迫切左外連結檢索 


(12)假設對Customer類的orders集合採用延遲檢索策略,編譯或運行以下程序,會出現什麼情況(單選) 
Session session=sessionFactory.openSession(); 
tx = session.beginTransaction(); 
Customer customer=(Customer)session.get(Customer.class,new Long(1)); 
tx.commit(); 
session.close(); 
Iterator orderIterator=customer.getOrders().iterator(); 


A)編譯出錯 B)編譯通過,並正常運行 C)編譯通過,但運行時拋出異常 


(13)關於HQL與SQL,以下哪些說法正確?(多選) 
A)HQL與SQL沒什麼差別 
B)HQL面向對象,而SQL操縱關係數據庫 
C)在HQL與SQL中,都包含select,insert,update,delete語句 
D)HQL僅用於查詢數據,不支持insert,update和delete語句 


(14)事務隔離級別是由誰實現的?(單選) 
A)Java應用程序 B)Hibernate C)數據庫系統 D)JDBC驅動程序 


(15)悲觀鎖與樂觀鎖,哪個具有較好的併發性能?(單選) 
A)悲觀鎖 B)樂觀鎖 


答案: 
(1)A,B,C (2)B,C (3)A (4)D (5)A,B,C,D,F (6)C (7)B (8)A,C,D (9)D   (10)F (11)C (12)C (13)B,D (14)C (15)B 
============================================================================





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章