Hibernate的面試題

*  比較Hibernate的三種檢索策略優缺點

1立即檢索;
優點:對應用程序完全透明,不管對象處於持久化狀態,還是遊離狀態,應用程序都可以方便的從一個對象導航到與它關聯的對象;
缺點:1.select語句太多;2.可能會加載應用程序不需要訪問的對象白白浪費許多內存空間;
2延遲檢索:
優點:由應用程序決定需要加載哪些對象,可以避免可執行多餘的select語句,以及避免加載應用程序不需要訪問的對象。因此能提高檢索性能,並且能節省內存空間;
缺點:應用程序如果希望訪問遊離狀態代理類實例,必須保證他在持久化狀態時已經被初始化;
3 迫切左外連接檢索
優點:1對應用程序完全透明,不管對象處於持久化狀態,還是遊離狀態,應用程序都可以方便地衝一個對象導航到與它關聯的對象。2使用了外連接,select語句數目少;
缺點:1 可能會加載應用程序不需要訪問的對象,白白浪費許多內存空間;2複雜的數據庫表連接也會影響檢索性能;

*  如何在控制檯看到hibernate生成並執行的sql

在定義數據庫和數據庫屬性的文件applicationConfig.xml裏面,把hibernate.show_sql 設置爲true
這樣生成的SQL就會在控制檯出現了
注意:這樣做會加重系統的負擔,不利於性能調優

*  hibernate都支持哪些緩存策略

Read-only:  這種策略適用於那些頻繁讀取卻不會更新的數據,這是目前爲止最簡單和最有效的緩存策略
* Read/write:這種策略適用於需要被更新的數據,比read-only更耗費資源,在非JTA環境下,每個事務需要在session.close和session.disconnect()被調用
* Nonstrict read/write: 這種策略不保障兩個同時進行的事務會修改同一塊數據,這種策略適用於那些經常讀取但是極少更新的數據
* Transactional: 這種策略是完全事務化得緩存策略,可以用在JTA環境下

* hibernate裏面的sorted collection 和ordered collection有什麼區別

sorted collection是在內存中通過java比較器進行排序的
ordered collection是在數據庫中通過order by進行排序的

*  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,objectcomposition
Hql:
1、 屬性查詢
2、 參數查詢、命名參數查詢
3、 關聯查詢
4、 分頁查詢
5、 統計函數

6. 如何優化Hibernate?
1.使用雙向一對多關聯,不使用單向一對多
2.靈活使用單向一對多關聯
3.不用一對一,用多對一取代
4.配置對象緩存,不使用集合緩存
5.一對多集合使用Bag,多對多集合使用Set
6. 繼承類使用顯式多態
7. 表字段要少,表關聯不要怕多,有二級緩存撐腰

7. Struts工作機制?爲什麼要使用Struts?
工作機制:
Struts的工作流程:
在web應用啓動時就會加載初始化ActionServlet,ActionServlet從
struts-config.xml文件中讀取配置信息,把它們存放到各種配置對象
當ActionServlet接收到一個客戶請求時,將執行如下流程.
-(1)檢索和用戶請求匹配的ActionMapping實例,如果不存在,就返回請求路徑無效信息;
-(2)如果ActionForm實例不存在,就創建一個ActionForm對象,把客戶提交的表單數據保存到ActionForm對象中;
-(3)根據配置信息決定是否需要表單驗證.如果需要驗證,就調用ActionForm的validate()方法;
-(4)如果ActionForm的validate()方法返回null或返回一個不包含ActionMessage的ActuibErrors對象, 就表示表單驗證成功;
-(5)ActionServlet根據ActionMapping所包含的映射信息決定將請求轉發給哪個Action,如果相應的Action實例不存在,就先創建這個實例,然後調用Action的execute()方法;
-(6)Action的execute()方法返回一個ActionForward對象,ActionServlet在把客戶請求轉發給 ActionForward對象指向的JSP組件;
-(7)ActionForward對象指向JSP組件生成動態網頁,返回給客戶;

爲什麼要用Struts:
JSP、Servlet、JavaBean技術的出現給我們構建強大的企業應用系統提供了可能。但用這些技術構建的系統非常的繁亂,所以在此之上,我們需要一個規則、一個把這些技術組織起來的規則,這就是框架,Struts便應運而生。

基於Struts開發的應用由3類組件構成:控制器組件、模型組件、視圖組件

8. Struts的validate框架是如何驗證的?
在struts配置文件中配置具體的錯誤提示,再在FormBean中的validate()方法具體調用。

9. 說下Struts的設計模式
MVC模式: web應用程序啓動時就會加載並初始化ActionServler。用戶提交表單時,一個配置好的ActionForm對象被創建,並被填入表單相應的數據,ActionServler根據Struts-config.xml文件配置好的設置決定是否需要表單驗證,如果需要就調用ActionForm的 Validate()驗證後選擇將請求發送到哪個Action,如果Action不存在,ActionServlet會先創建這個對象,然後調用 Action的execute()方法。Execute()從ActionForm對象中獲取數據,完成業務邏輯,返回一個ActionForward對象,ActionServlet再把客戶請求轉發給ActionForward對象指定的jsp組件,ActionForward對象指定的jsp生成動態的網頁,返回給客戶。

10. spring工作機制及爲什麼要用?
1.spring mvc請所有的請求都提交給DispatcherServlet,它會委託應用系統的其他模塊負責負責對請求進行真正的處理工作。
2.DispatcherServlet查詢一個或多個HandlerMapping,找到處理請求的Controller.
3.DispatcherServlet請求提交到目標Controller
4.Controller進行業務邏輯處理後,會返回一個ModelAndView
5.Dispathcher查詢一個或多個ViewResolver視圖解析器,找到ModelAndView對象指定的視圖對象
6.視圖對象負責渲染返回給客戶端。

爲什麼用Spring:
{AOP 讓開發人員可以創建非行爲性的關注點,稱爲橫切關注點,並將它們插入到應用程序代碼中。使用 AOP 後,公共服務  (比 如日誌、持久性、事務等)就可以分解成方面並應用到域對象上,同時不會增加域對象的對象模型的複雜性。
IOC 允許創建一個可以構造對象的應用環境,然後向這些對象傳遞它們的協作對象。正如單詞 倒置 所表明的,IOC就像反 過來的 JNDI。沒有使用一堆抽象工廠、服務定位器、單元素(singleton)和直接構造(straight construction),每一個對象都是用其協作對象構造的。因此是由容器管理協作對象(collaborator)。
Spring即使一個AOP框架,也是一IOC容器。 Spring 最好的地方是它有助於您替換對象。有了 Spring,只要用 JavaBean 屬性和配置文件加入依賴性(協作對象)。然後可以很容易地在需要時替換具有類似接口的協作對象。}

*  hibernate 面試題小集

1. Hibernate有哪幾種查詢數據的方式

3種:hql、條件查詢QBC(QueryBy Criteria)、原生sql (通過createSQLQuery建立)

2. 談談Hibernate中inverse的作用

inverse屬性默認是false,就是說關係的兩端都來維護關係。
比如Student和Teacher是多對多關係,用一箇中間表TeacherStudent維護。Gp)i
如果Student這邊inverse=”true”, 那麼關係由另一端Teacher維護,就是說當插入Student時,不會操作TeacherStudent表(中間表)。只有Teacher插入或刪除時纔會觸發對中間表的操作。所以兩邊都inverse=”true”是不對的,會導致任何操作都不觸發對中間表的影響;當兩邊都inverse=”false”或默認時,會導致在中間表中插入兩次關係。

3. 說說Hibernate中的update()和saveOrUpdate()的區別,session的load()和get()的區別。

saveOrUpdate()方法可以實現update()的功能,但會多些步驟,具體如下:
如果對象在該session中已經被持久化,不進行操作;對象的標識符屬性(identifier property)在數據庫中不存在或者是個暫時的值,調用save()方法保存它;如果session中的另一個對象有相同的標識符拋出一個異常;以上皆不符合則調用update()更新之。
Session.load/get方法均可以根據指定的實體類和id從數據庫讀取記錄,並返回與之對應的實體對象。session的get()和load()其區別在於:
如果未能發現符合條件的記錄,get方法返回null,而load方法會拋出一個ObjectNotFoundException;load方法可返回實體的代理類實例,而get方法永遠直接返回實體類;load方法可以充分利用內部緩存和二級緩存中的現有數據,而get方法則僅僅在內部緩存中進行數據查找,如沒有發現對應數據,將越過二級緩存,直接調用SQL完成數據讀取。

*  hibernate中對象的三種狀態

瞬時態(Transient)、持久態(Persistent)、脫管態(Detached)。處於持久態的對象也稱爲PO(Persistence Object),瞬時對象和脫管對象也稱爲VO(Value Object)。

瞬時態

由new命令開闢內存空間的java對象,

eg. Person person =new Person(”amigo”, “女”);

如果沒有變量對該對象進行引用,它將被java虛擬機回收。

瞬時對象在內存孤立存在,它是攜帶信息的載體,不和數據庫的數據有任何關聯關係,在Hibernate中,可通過session的save()或 saveOrUpdate()方法將瞬時對象與數據庫相關聯,並將數據對應的插入數據庫中,此時該瞬時對象轉變成持久化對象。

持久態

處於該狀態的對象在數據庫中具有對應的記錄,並擁有一個持久化標識。如果是用hibernate的delete()方法,對應的持久對象就變成瞬時對象,因數據庫中的對應數據已被刪除,該對象不再與數據庫的記錄關聯。

當一個session執行close()或clear()、evict()之後,持久對象變成脫管對象,此時持久對象會變成脫管對象,此時該對象雖然具有數據庫識別值,但它已不在HIbernate持久層的管理之下。

持久對象具有如下特點:

1. 和session實例關聯;n

2. 在數據庫中有與之關聯的記錄。

脫管態

當與某持久對象關聯的session被關閉後,該持久對象轉變爲脫管對象。當脫管對象被重新關聯到session上時,並再次轉變成持久對象。

脫管對象擁有數據庫的識別值,可通過update()、saveOrUpdate()等方法,轉變成持久對象。

脫管對象具有如下特點:

1. 本質上與瞬時對象相同,在沒有任何變量引用它時,JVM會在適當的時候將它回收;

2.   比瞬時對象多了一個數據庫記錄標識值。4RESA3ES  B

*  Detached Object(遊離對象)有什麼好處

Detached Object(遊離對象)可以傳遞到任何層直到表現層而不是用任何DTO(DataTransfer Objects). 然後你還可以重新把遊離對象賦給另外一個Session.

*  JDBC hibernate 和 ibatis 的區別

jdbc:手動
  手動寫sql
  delete、insert、update要將對象的值一個一個取出傳到sql中,不能直接傳入一個對象。
  select:返回的是一個resultset,要從ResultSet中一行一行、一個字段一個字段的取出,然後封裝到一個對象中,不直接返回一個對象。
 ibatis的特點:半自動化
  sql要手動寫
  delete、insert、update:直接傳入一個對象
  select:直接返回一個對象   
 hibernate:全自動
  不寫sql,自動封裝
  delete、insert、update:直接傳入一個對象
  select:直接返回一個對象

*  hibernate如何實現數據表映射的繼承關係

1、兩個表,子類重複父類的屬性。
 2、一個表,子類父類共用一個表
    <class name=”Users” table=”users”discriminator-value=”Users”>
   <discriminator column=”DISCRIMINATOR_USERTYPE”type=”string”/>
<subclass name=”admin” discriminator-value=”admin”>
           <propertyname=”adminRemark” column=”admin_remark” type=”string” />
        </subclass>
    </class>
 3、兩個表,子類引用父類的主鍵,享用公共的字段或屬性。
    <class name=”Users” table=”users”>
        <id name=”userid” column=”USERID”type=”string”>
           <generator class=”assigned”/>
        </id>
        <property name=”pwd” column=”pwd”type=”string” />
   <joined-subclass name=”Guest” table=”guest”>
    <key column=”USERID”/>
         <propertyname=”guestRemark” column=”guest_remark” type=”string” />
        </joined-subclass>
</class>
批量刪除
 Query query=session.createQuery(”update”或”delete”);
 query.executeUpdate();

*  hibernate中Query對象的使用

1 個或多個屬性查詢:
 Query query=session.createQuery(”select customername,customerid fromCustomer”)
 List l=query.list();
 For(int i=0;i<l.size();i++)
{
 Obejct[] object=(Object[])l.get(i);
 Object[0]  object[1]
}
}
分組: “select count(*),productname from Product group byproductname order by productname”
取值與屬性一樣
配置的查詢,在*.hbm.xml中
 <query name=”sql”>
    <![CDATA[
     from Product where productid=:productid
    ]]>
</query>
 Query query=session.getNamedQuery(sql);
聯接1
 ”from Customer as customer join fetch customer.buySet”:將多的放到buySet屬性中,得出的結是Customer有一個,Buy有多個
聯接2
“from Customer as customer join customer.buySet”:得出的對象,customer與buy是1對1
子查詢:
 ”from Customer as customer where (select count(*) from customer.buySet)>1″

*  hibernate中Criteria和DetachedCriteria的作用是什麼?

Criteriac=session.createCriteria(Customer.class);
 //設置條件
 c.add(Expression.ge(“字段名”,”值對象”))
  ge:>=
  gt:>
  le:<=
  lt:<
  eq:=
 //排序
  c.addOrder(Order.asc(“字段名”))
 //分頁
  c.setFirstResult(1)//從第2行開始提取
  c.setMaxResults(5)//返回5行

 DetachedCriteria產生時不需要session
 DetachedCriteria dc= DetachedCriteria.forClass(Customer.class)
 Criteriac=Dc.getExecutableCriteria(session)

*  hibernate中數據表映射關係主要有什麼類型?

one-to-many
 inverse:主控方,外鍵的關係有誰控制
  inverse=false 是主控方,外鍵是由它控制的   
  inverse=true 是被控方,外鍵與它沒關係
  要想實現主控方的控制必須將被控方作爲主控方的屬性
 cascade:級聯
  主表增從表增
  主表修從表修
  主表刪從表刪
 lazy:延遲
  lazy=false:一下將所有的內容取出,不延時(常用)
  lazy=true:取出部分內容,其餘內容動態去取
  通過get可以取出對方的所有內容

*  hibernate的核心是什麼,他們的相互關係是什麼,重要的方法是什麼

Configuration
SessionFactory
  Session如下方法
   Save
   load
   Update
   Delete
      Query q=CreateQuery(“from Customer wherecustomerName=:customerName”)
   beginTransaction
   close
   Transaction
   Commit()

*  MyEclipse加入hibernate的全過程是什麼

1.Db-browers加入配置連接
2.新建工程
3.加入hibernate環境,指定*.hbm.xml及HibernateSessionFactory文件所在的位置

*  面試中常出現的兩個hibernate面試題及答案

1.在數據庫中條件查詢速度很慢的時候,如何優化?
1.建索引
2.減少表之間的關聯
3.優化sql,儘量讓sql很快定位數據,不要讓sql做全表查詢,應該走索引,把數據量大的表排在前面
4.簡化查詢字段,沒用的字段不要,已經對返回結果的控制,儘量返回少量數據

2.在hibernate中進行多表查詢,每個表中各取幾個字段,也就是說查詢出來的結果集並沒有一個實體類與之對應,如何解決這個問題?
解決方案一,按照Object[]數據取出數據,然後自己組bean
解決方案二,對每個表的bean寫構造函數,比如表一要查出field1,field2兩個字段,那麼有一個構造函數就是Bean(type1 filed1,type2 field2) ,然後在hql裏面就可以直接生成這個bean了。具體怎麼用請看相關文檔,我說的不是很清楚。
session.load()和session.get()的區別
Session.load/get方法均可以根據指定的實體類和id從數據庫讀取記錄,並返回與之對應的實體對象。其區別在於:

如果未能發現符合條件的記錄,get方法返回null,而load方法會拋出一個ObjectNotFoundException。
Load方法可返回實體的代理類實例,而get方法永遠直接返回實體類。
load方法可以充分利用內部緩存和二級緩存中的現有數據,而get方法則僅僅在內部緩存中進行數據查找,如沒有發現對應數據,將越過二級緩存,直接調用SQL完成數據讀取。
Session在加載實體對象時,將經過的過程:

首先,Hibernate中維持了兩級緩存。第一級緩存由Session實例維護,其中保持了Session當前所有關聯實體的數據,也稱爲內部緩存。而第二級緩存則存在於SessionFactory層次,由當前所有由本 SessionFactory構造的Session實例共享。出於性能考慮,避免無謂的數據庫訪問,Session在調用數據庫查詢功能之前,會先在緩存中進行查詢。首先在第一級緩存中,通過實體類型和id進行查找,如果第一級緩存查找命中,且數據狀態合法,則直接返回。
之後,Session會在當前“NonExists”記錄中進行查找,如果“NonExists”記錄中存在同樣的查詢條件,則返回null。 “NonExists”記錄了當前Session實例在之前所有查詢操作中,未能查詢到有效數據的查詢條件(相當於一個查詢黑名單列表)。如此一來,如果 Session中一個無效的查詢條件重複出現,即可迅速作出判斷,從而獲得最佳的性能表現。
對於load方法而言,如果內部緩存中未發現有效數據,則查詢第二級緩存,如果第二級緩存命中,則返回。
如在緩存中未發現有效數據,則發起數據庫查詢操作(Select SQL),如經過查詢未發現對應記錄,則將此次查詢的信息在“NonExists”中加以記錄,並返回null。
根據映射配置和Select SQL得到的ResultSet,創建對應的數據對象。
將其數據對象納入當前Session實體管理容器(一級緩存)。
執行Interceptor.onLoad方法(如果有對應的Interceptor)。
將數據對象納入二級緩存。
如果數據對象實現了LifeCycle接口,則調用數據對象的onLoad方法。
返回數據對象。
Hibernate的主鍵生成機制
1) assigned
主鍵由外部程序負責生成,無需Hibernate參與。
2) hilo
通過hi/lo 算法實現的主鍵生成機制,需要額外的數據庫表保存主鍵生成歷史狀態。
3) seqhilo
與hilo 類似,通過hi/lo 算法實現的主鍵生成機制,只是主鍵歷史狀態保存在Sequence中,適用於支持Sequence的數據庫,如Oracle。
4) increment
主鍵按數值順序遞增。此方式的實現機制爲在當前應用實例中維持一個變量,以保存着當前的最大值,之後每次需要生成主鍵的時候將此值加1作爲主鍵。這種方式可能產生的問題是:如果當前有多個實例訪問同一個數據庫,那麼由於各個實例各自維護主鍵狀態,不同實例可能生成同樣的主鍵,從而造成主鍵重複異常。因此,如果同一數據庫有多個實例訪問,此方式必須避免使用。
5) identity
採用數據庫提供的主鍵生成機制。如DB2、SQL Server、MySQL中的主鍵生成機制。
6) sequence
採用數據庫提供的sequence 機制生成主鍵。如Oralce中的Sequence。
7) native
由Hibernate根據底層數據庫自行判斷採用identity、hilo、sequence其中一種作爲主鍵生成方式。
8) uuid.hex
由Hibernate基於128 位唯一值產生算法生成16 進制數值(編碼後以長度32 的字符串表示)作爲主鍵。
9) uuid.string
與uuid.hex 類似,只是生成的主鍵未進行編碼(長度16)。在某些數據庫中可能出現問題(如PostgreSQL)。
10) foreign
使用外部表的字段作爲主鍵。一般而言,利用uuid.hex方式生成主鍵將提供最好的性能和數據庫平臺適應性。
這10中生成OID標識符的方法,increment 比較常用,把標識符生成的權力交給Hibernate處理.但是當同時多個Hibernate應用操作同一個數據庫,甚至同一張表的時候.就推薦使用identity依賴底層數據庫實現,但是數據庫必須支持自動增長,當然針對不同的數據庫選擇不同的方法.如果你不能確定你使用的數據庫具體支持什麼的情況下.可以選擇用native 讓Hibernate來幫選擇identity,sequence,或hilo.
另外由於常用的數據庫,如Oracle、DB2、SQLServer、MySql 等,都提供了易用的主鍵生成機制(Auto-Increase 字段或者Sequence)。我們可以在數據庫提供的主鍵生成機制上,採用generator-class=native的主鍵生成方式。
不過值得注意的是,一些數據庫提供的主鍵生成機制在效率上未必最佳,大量併發insert數據時可能會引起表之間的互鎖。數據庫提供的主鍵生成機制,往往是通過在一個內部表中保存當前主鍵狀態(如對於自增型主鍵而言,此內部表中就維護着當前的最大值和遞增量),之後每次插入數據會讀取這個最大值,然後加上遞增量作爲新記錄的主鍵,之後再把這個新的最大值更新回內部表中,這樣,一次Insert操作可能導致數據庫內部多次表讀寫操作,同時伴隨的還有數據的加鎖解鎖操作,這對性能產生了較大影響。因此,對於併發Insert要求較高的系統,推薦採用uuid.hex 作爲主鍵生成機制

*  網友自己出的幾道 spring 面試題

1、 簡述你對IoC(Inversion of Control)的理解,描述一下Spring中實現DI(Dependency Injection)的幾種方式。

spring的IOC有三種注入方式  第一是根據屬性注入  也叫set方法注入;第二種是根據構造方法進行注入;第三種是根據註解進行注入,這種方式我認爲比較好,方便,要是bean多的話,使用前兩種方式會使得配置文件過於臃腫。

2、 Spring的Bean有多種作用域,包括:
singleton、prototype、request、session、globalsession、application、自定義

3、 簡單描述Spring Framework與Struts的不同之處,整合Spring與Struts有哪些方法,哪種最好,爲什麼?

答、 Spring是完整的一站式框架,而Struts僅是MVC框架,且着重於MVC中的C。Spring有三種方式整合Struts:使用 Spring 的 ActionSupport 類整合 Struts;使用 Spring 的DelegatingRequestProcessor 覆蓋 Struts 的 RequestProcessor;將 Struts Action 管理委託給 Spring 框架,動作委託最好。(詳見使用Spring 更好地處理Struts 動作)

Spring 2.0新增一種方式:AutowiringRequestProcessor。(詳見http://www.javaeye.com/topic/24239)

4、 Hibernate中的update()和saveOrUpdate()的區別

答、saveOrUpdate()方法可以實現update()的功能,但會多些步驟,具體如下:

如果對象在該session中已經被持久化,不進行操作;

對象的標識符屬性(identifierproperty)在數據庫中不存在或者是個暫時的值,調用save()方法保存它;

如果session中的另一個對象有相同的標識符拋出一個異常;

以上皆不符合則調用update()更新之。

5、 Spring對多種ORM框架提供了很好的支持,簡單描述在Spring中使用Hibernate的方法,並結合事務管理。

答、 在context中定義DataSource,創建SessionFactoy,設置參數;DAO類繼承HibernateDaoSupport,實現具體接口,從中獲得HibernateTemplate進行具體操作。

在使用中如果遇到OpenSessionInView的問題,可以添加OpenSessionInViewFilter或OpenSessionInViewInterceptor。(詳見Spring framework 2.0 Reference的12.2節Hibernate)

聲明式事務需聲明事務管理器,在context中設置指定屬性,用確定和。

 *  請你談談SSH整合

SSH:
Struts(表示層)+Spring(業務層)+Hibernate(持久層)
Struts:
Struts是一個表示層框架,主要作用是界面展示,接收請求,分發請求。
在MVC框架中,Struts屬於VC層次,負責界面表現,負責MVC關係的分發。(View:沿用JSP,HTTP,Form,Tag,Resourse ;Controller:ActionServlet,struts-config.xml,Action)
Hibernate:
Hibernate是一個持久層框架,它只負責與關係數據庫的操作。
Spring:
Spring是一個業務層框架,是一個整合的框架,能夠很好地黏合表示層與持久層。

*  hibernate面試題:怎麼得到一個Collection的大小而不用初始化它

Integer size = (Integer) s.createFilter( collection, "select count(*)" ).uniqueResult();

*  hibernate面試題:怎麼得到查詢結果的記錄數而不用返回查詢結果

Integer count = (Integer) session.createQuery("select count(*) from ....").uniqueResult();

*  什麼是SessionFactory,她是線程安全麼?

SessionFactory isHibernates concept of a single datastore and is threadsafe so that many threadscan access it concurrently and request for sessions and immutable cache ofcompiled mappings for a single database. A SessionFactory is usually only builtonce at startup. SessionFactory should be wrapped in some kind of singleton sothat it can be easily accessed in an application code.

SessionFactorysessionFactory = new Configuration().configure().buildSessionfactory();

SessionFactory 是Hibrenate單例數據存儲和線程安全的,以至於可以多線程同時訪問。一個SessionFactory 在啓動的時候只能建立一次。SessionFactory應該包裝各種單例以至於它能很簡單的在一個應用代碼中儲存.

*  如何配置Hibernate?

The configurationfiles hibernate.cfg.xml (or hibernate.properties) and mapping files *.hbm.xmlare used by the Configuration class to create (i.e. configure and bootstraphibernate) the SessionFactory, which in turn creates the Session instances.Session instances are the primary interface for the persistence service.

” hibernate.cfg.xml(alternatively can use hibernate.properties): These two files are used toconfigure the hibernate sevice (connection driver class, connection URL,connection username, connection password, dialect etc). If both files arepresent in the classpath then hibernate.cfg.xml file overrides the settingsfound in the hibernate.properties file.

” Mapping files(*.hbm.xml): These files are used to map persistent objects to a relationaldatabase. It is the best practice to store each object in an individual mappingfile (i.e mapping file per class) because storing large number of persistentclasses into one mapping file can be difficult to manage and maintain. Thenaming convention is to use the same name as the persistent (POJO) class name.For example Account.class will have a mapping file named Account.hbm.xml.Alternatively hibernate annotations can be used as part of your persistentclass code instead of the *.hbm.xml files.

*  優化hibernate性能的幾點建議

1、針對oracle數據庫而言,Fetch Size 是設定JDBC的Statement讀取數據的時候每次從數據庫中取出的記錄條數,一般設置爲30、50、100。Oracle數據庫的JDBC驅動默認的FetchSize=15,設置Fetch Size設置爲:30、50,性能會有明顯提升,如果繼續增大,超出100,性能提升不明顯,反而會消耗內存。

即在hibernate配製文件中進行配製:

1 <property name=”hibernateProperties”>
2 <props>
3 <prop key=”hibernate.dialect”>org.hibernate.dialect.Oracle9Dialect</prop>
4 <prop key=”hibernate.show_sql”>false</prop>
5 <!– Create/update the database tables automaticallywhen the JVM starts up
6 <prop key=”hibernate.hbm2ddl.auto”>update</prop> –>
7 <!– Turn batching off for better error messages underPostgreSQL
8 <prop key=”hibernate.jdbc.batch_size”>100</prop> –>
9 <prop key=”hibernate.jdbc.batch_size”>50</prop>
10 </props>
11 </property>Fetch Size設的越大,讀數據庫的次數越少,速度越快;Fetch Size越小,讀數據庫的次數越多,速度越慢。
2、如果是超大的系統,建議生成htm文件。加快頁面提升速度。

3、不要把所有的責任推在hibernate上,對代碼進行重構,減少對數據庫的操作,儘量避免在數據庫查詢時使用in操作,以及避免遞歸查詢操作,代碼質量、系統設計的合理性決定系統性能的高低。

4、 對大數據量查詢時,慎用list()或者iterator()返回查詢結果,

(1). 使用List()返回結果時,Hibernate會所有查詢結果初始化爲持久化對象,結果集較大時,會佔用很多的處理時間。

(2). 而使用iterator()返回結果時,在每次調用iterator.next()返回對象並使用對象時,Hibernate才調用查詢將對應的對象初始化,對於大數據量時,每調用一次查詢都會花費較多的時間。當結果集較大,但是含有較大量相同的數據,或者結果集不是全部都會使用時,使用iterator()纔有優勢。

5、在一對多、多對一的關係中,使用延遲加載機制,會使不少的對象在使用時方會初始化,這樣可使得節省內存空間以及減少數據庫的負荷,而且若PO中的集合沒有被使用時,就可減少互數據庫的交互從而減少處理時間。

6、對含有關聯的PO(持久化對象)時,若default-cascade=”all”或者 “save-update”,新增PO時,請注意對PO中的集合的賦值操作,因爲有可能使得多執行一次update操作。

7、 對於大數據量新增、修改、刪除操作或者是對大數據量的查詢,與數據庫的交互次數是決定處理時間的最重要因素,減少交互的次數是提升效率的最好途徑,所以在開發過程中,請將show_sql設置爲true,深入瞭解Hibernate的處理過程,嘗試不同的方式,可以使得效率提升。儘可能對每個頁面的顯示,對數據庫的操作減少到100—-150條以內。越少越好。

*  如何進行hibernate性能調優

大體上,對於HIBERNATE性能調優的主要考慮點如下:
Ø 數據庫設計調整
Ø HQL優化
Ø API的正確使用(如根據不同的業務類型選用不同的集合及查詢API)
Ø 主配置參數(日誌,查詢緩存,fetch_size,batch_size等)
Ø 映射文件優化(ID生成策略,二級緩存,延遲加載,關聯優化)
Ø 一級緩存的管理
Ø 針對二級緩存,還有許多特有的策略
Ø 事務控制策略。
1、 數據庫設計
a) 降低關聯的複雜性
b) 儘量不使用聯合主鍵
c) ID的生成機制,不同的數據庫所提供的機制並不完全一樣
d) 適當的冗餘數據,不過分追求高範式
2、 HQL優化
HQL如果拋開它同HIBERNATE本身一些緩存機制的關聯,HQL的優化技巧同普通的SQL優化技巧一樣,可以很容易在網上找到一些經驗之談。
3、 主配置
a) 查詢緩存,同下面講的緩存不太一樣,它是針對HQL語句的緩存,即完全一樣的語句再次執行時可以利用緩存數據。但是,查詢緩存在一個交易系統(數據變更頻繁,查詢條件相同的機率並不大)中可能會起反作用:它會白白耗費大量的系統資源但卻難以派上用場。
b) fetch_size,同JDBC的相關參數作用類似,參數並不是越大越好,而應根據業務特徵去設置
c) batch_size同上。
d) 生產系統中,切記要關掉SQL語句打印。
4、 緩存
a) 數據庫級緩存:這級緩存是最高效和安全的,但不同的數據庫可管理的層次並不一樣,比如,在ORACLE中,可以在建表時指定將整個表置於緩存當中。
b) SESSION緩存:在一個HIBERNATESESSION有效,這級緩存的可干預性不強,大多於HIBERNATE自動管理,但它提供清除緩存的方法,這在大批量增加/更新操作是有效的。比如,同時增加十萬條記錄,按常規方式進行,很可能會發現OutofMemeroy的異常,這時可能需要手動清除這一級緩存:Session.evict以及Session.clear
c) 應用緩存:在一個SESSIONFACTORY中有效,因此也是優化的重中之重,因此,各類策略也考慮的較多,在將數據放入這一級緩存之前,需要考慮一些前提條件:
i. 數據不會被第三方修改(比如,是否有另一個應用也在修改這些數據?)
ii. 數據不會太大
iii. 數據不會頻繁更新(否則使用CACHE可能適得其反)
iv. 數據會被頻繁查詢
v. 數據不是關鍵數據(如涉及錢,安全等方面的問題)。
緩存有幾種形式,可以在映射文件中配置:read-only(只讀,適用於很少變更的靜態數據/歷史數據),nonstrict-read-write,read-write(比較普遍的形式,效率一般),transactional(JTA中,且支持的緩存產品較少)
d) 分佈式緩存:同c)的配置一樣,只是緩存產品的選用不同,在目前的HIBERNATE中可供選擇的不多,oscache, jboss cache,目前的大多數項目,對它們的用於集羣的使用(特別是關鍵交易系統)都持保守態度。在集羣環境中,只利用數據庫級的緩存是最安全的。
5、 延遲加載
a) 實體延遲加載:通過使用動態代理實現
b) 集合延遲加載:通過實現自有的SET/LIST,HIBERNATE提供了這方面的支持
c) 屬性延遲加載:
6、 方法選用
a) 完成同樣一件事,HIBERNATE提供了可供選擇的一些方式,但具體使用什麼方式,可能用性能/代碼都會有影響。顯示,一次返回十萬條記錄(List/Set/Bag/Map等)進行處理,很可能導致內存不夠的問題,而如果用基於遊標(ScrollableResults)或Iterator的結果集,則不存在這樣的問題。
b) Session的load/get方法,前者會使用二級緩存,而後者則不使用。
c) Query和list/iterator,如果去仔細研究一下它們,你可能會發現很多有意思的情況,二者主要區別(如果使用了Spring,在HibernateTemplate中對應find,iterator方法):
i. list只能利用查詢緩存(但在交易系統中查詢緩存作用不大),無法利用二級緩存中的單個實體,但list查出的對象會寫入二級緩存,但它一般只生成較少的執行SQL語句,很多情況就是一條(無關聯)。
ii. iterator則可以利用二級緩存,對於一條查詢語句,它會先從數據庫中找出所有符合條件的記錄的ID,再通過ID去緩存找,對於緩存中沒有的記錄,再構造語句從數據庫中查出,因此很容易知道,如果緩存中沒有任何符合條件的記錄,使用iterator會產生N+1條SQL語句(N爲符合條件的記錄數)
iii. 通過iterator,配合緩存管理API,在海量數據查詢中可以很好的解決內存問題,如:
while(it.hasNext()){
YouObject object = (YouObject)it.next();
session.evict(youObject);
sessionFactory.evice(YouObject.class, youObject.getId());
}
如果用list方法,很可能就出OutofMemory錯誤了。
iv. 通過上面的說明,我想你應該知道如何去使用這兩個方法了。
7、 集合的選用
在HIBERNATE 3.1文檔的“19.5.Understanding Collection performance”中有詳細的說明。
8、 事務控制
事務方面對性能有影響的主要包括:事務方式的選用,事務隔離級別以及鎖的選用
a) 事務方式選用:如果不涉及多個事務管理器事務的話,不需要使用JTA,只有JDBC的事務控制就可以。
b) 事務隔離級別:參見標準的SQL事務隔離級別
c) 鎖的選用:悲觀鎖(一般由具體的事務管理器實現),對於長事務效率低,但安全。樂觀鎖(一般在應用級別實現),如在HIBERNATE中可以定義VERSION字段,顯然,如果有多個應用操作數據,且這些應用不是用同一種樂觀鎖機制,則樂觀鎖會失效。因此,針對不同的數據應有不同的策略,同前面許多情況一樣,很多時候我們是在效率與安全/準確性上找一個平衡點,無論如何,優化都不是一個純技術的問題,你應該對你的應用和業務特徵有足夠的瞭解。
9、 批量操作
即使是使用JDBC,在進行大批數據更新時,BATCH與不使用BATCH有效率上也有很大的差別。我們可以通過設置batch_size來讓其支持批量操作。
舉個例子,要批量刪除某表中的對象,如“delete Account”,打出來的語句,會發現HIBERNATE找出了所有ACCOUNT的ID,再進行刪除,這主要是爲了維護二級緩存,這樣效率肯定高不了,在後續的版本中增加了bulkdelete/update,但這也無法解決緩存的維護問題。也就是說,由於有了二級緩存的維護問題,HIBERNATE的批量操作效率並不盡如人意!
從前面許多要點可以看出,很多時候我們是在效率與安全/準確性上找一個平衡點,無論如何,優化都不是一個純技術的問題,你應該對你的應用和業務特徵有足夠的瞭解,一般的,優化方案應在架構設計期就基本確定,否則可能導致沒必要的返工,致使項目延期,而作爲架構師和項目經理,還要面對開發人員可能的抱怨,必竟,我們對用戶需求更改的控制力不大,但技術/架構風險是應該在初期意識到並制定好相關的對策。
還有一點要注意,應用層的緩存只是錦上添花,永遠不要把它當救命稻草,應用的根基(數據庫設計,算法,高效的操作語句,恰當API的選擇等)纔是最重要的。

*  JDBC ,hibernate分頁顯示怎麼實現?

答:方法分別爲:
1) Hibernate 的分頁:
Query query = session.createQuery(”from Student”);
query.setFirstResult(firstResult);//設置每頁開始的記錄號
query.setMaxResults(resultNumber);//設置每頁顯示的記錄數
Collection students = query.list();
2) JDBC 的分頁:根據不同的數據庫採用不同的sql 分頁語句
例如: Oracle 中的sql 語句爲: “SELECT * FROM (SELECT a.*, rownum r FROM
TB_STUDENT) WHERE r between 2 and 10″ 查詢從記錄號2 到記錄號10 之間的
所有記錄。

Hibernate的應用(hibernate的結構)

答://首先獲得SessionFactory 的對象
SessionFactory sessionFactory = new Configuration().configure().
buildSessionFactory();
//然後獲得session 的對象
Session session = sessionFactory.openSession();
//其次獲得Transaction 的對象
Transaction tx = session.beginTransaction();
//執行相關的數據庫操作:增,刪,改,查
session.save(user); //增加, user 是User 類的對象
session.delete(user); //刪除
session.update(user); //更新
Query query = session.createQuery(“from User”); //查詢
List list = query.list();
//提交事務
tx.commit();
//如果有異常,我們還要作事務的回滾,恢復到操作之前
tx.rollback();
//最後還要關閉session,釋放資源
session.close();

*  關於hibernate的幾個面試題(無答案)

1)在hibernate 中,在配置文件呈標題一對多,多對多的標籤是什麼;
2)Hibernate 的二級緩存是什麼;
3)Hibernate 是如何處理事務的;
答:1)一對多的標籤爲<one-to-many> ;多對多的標籤爲<many-to-many>;
2)sessionFactory 的緩存爲hibernate 的二級緩存;
3)Hibernate 的事務實際上是底層的JDBCTransaction 的封裝或者是JTA
Transaction 的封裝;默認情況下使用JDBCTransaction

*  Hibernate的五個核心接口

Configuration 接口:配置Hibernate,根據其啓動hibernate,創建
SessionFactory 對象;
SessionFactory 接口:初始化Hibernate,充當數據存儲源的代理,創建
session 對象,sessionFactory 是線程安全的,意味着它的同一個實例可以被應
用的多個線程共享,是重量級、二級緩存;
Session 接口:負責保存、更新、刪除、加載和查詢對象,是線程不安全的,
避免多個線程共享同一個session,是輕量級、一級緩存;
Transaction 接口:管理事務;
Query 和Criteria 接口:執行數據庫的查詢。

*  如何優化hibernate

1. 使用雙向一對多關聯,不使用單向一對多
2. 靈活使用單向一對多關聯
3. 不用一對一,用多對一取代
4. 配置對象緩存,不使用集合緩存
5. 一對多集合使用Bag,多對多集合使用Set
6. 繼承類使用顯式多態
7. 表字段要少,表關聯不要怕多,有二級緩存撐腰

*  說下hibernate的緩存機制

1. 內部緩存存在Hibernate中又叫一級緩存,屬於應用事物級緩存
2. 二級緩存:
a) 應用及緩存
b) 分佈式緩存
條件:數據不會被第三方修改、數據大小在可接受範圍、數據更新頻率低、同一數據被系統頻繁使用、非關鍵數據
c) 第三方緩存的實現

*  hibernate怎麼實現類之間的關係

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

*  hibernate如何實現延遲加載

1. Hibernate2延遲加載實現:a)實體對象 b)集合(Collection)
2. Hibernate3 提供了屬性的延遲加載功能
當Hibernate在查詢數據的時候,數據並沒有存在與內存中,當程序真正對數據的操作時,對象才存在與內存中,就實現了延遲加載,他節省了服務器的內存開銷,從而提高了服務器的性能。

*  Hibernate數據查詢的幾種方式

1.使用主鍵id加載對象(load(),get());

2.通過對象導航,比如通過stu.getTeam()得到team的實例;

3 使用hql;

4使用qbc(query by criteria)

5直接使用sql語句取得記錄集;

一般都使用後面三種方式.

注意.hql是面向對象的查詢.語法和sql是基本一樣的.不區分大小寫的,但是注意的是對與對象.必須遵循對象的大小寫.因爲hql是對像查詢..同時我們必須清楚.hql只能取得對象,而不支持uid(update,insert.delete)

*  Hibernate中:不看數據庫,不看XML文件,不看查詢語句,怎麼能知道表的結構

看錶結構對應的類文件,比如UserInfo表對應的UserInfo.java文件

發佈了72 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章