Hibernate框架
簡介
Hibernate是一個典型的ORM框架。可以實現對象和記錄之間的轉化,從而完成數據庫的訪問操作,爲應用程序構建一個持久層。
Hibernate框架主要結構
1. hibernate.cfg.xml
主配置文件,用於定義數據庫連接參數和框架參數。
2. 實體類
用於實現和數據庫表記錄的映射,參考表結構編寫
3. 映射描述信息
- 可以用XML描述,需要編寫hbm.xml文件
- 利用註解描述,直接寫在實體類中
4. Hibernate 操作API
- Configuration 對象,用於加載hibernate.cfg.xml配置文件
- SessionFactory對象,用於創建Session對象
- Session對象,提供增刪改查方法
註解描述
- @Entity 表實體類
- @Table 與指定數據庫表關聯
- @Id 主鍵
- @Column 關聯字段
- < mapping class=”cn.xdl.entity.Dept” /> //添加映射實體類地址
對象操作
- session.get查詢,等價於findById
- session.save添加
- session.update更新
- session.delete刪除
5. 查詢操作
- 使用HQL操作
HQL語句使用類名和屬性名,區分大小寫
- HQL語句語法結構和SQL一樣
- HQL語句不能使用select *,省略即可
- HQL語句不能使用數據庫字符傳、日期、數值、SYSDATE等數據庫特有函數
- HQL語句不能使用join…on…中的on子句
HQL: from Dept where name like ?
Query query = session.createQuery(hql);
- 使用Criteria操作
//等價於from Dept
Criteria c = session.createCriteria(Dept.class);
- 使用Native SQL操作
SQL: select * from dept where dname like ? SQLQuery query =
session.createSQLQuery(sql);
延遲加載
1. 簡介
在使用一些查詢方法時,方法執行了,但是並沒有立刻發送SQL語句查詢數據庫。而是在訪問對象的getXxx時才觸發SQL執行加載對象數據。
session.load()/query.iterator()/關聯映射
2. 使用延遲加載方法時容易產生下面錯誤(重要)
org.hibernate.LazyInitializationException: could not initialize proxy
- no Session 原因:使用了延遲加載方法,但是session關閉早了。請求–>Action–>Service–>Dao(load)–>Result–>JSP(EL)–>關閉session
在Dao組件中不要關閉session對象,可以使用攔截器、Filter將session關閉插入到JSP解析之後。在Spring中提供了OpenSessionInViewFilter組件,只要在web.xml配置一下即可。
3. 延遲加載原理
動態代理技術。Spring AOP採用技術CGLIB和java Proxy API.
Hibernate採用的是javassist工具
4. 爲什麼用延遲加載
- 延遲加載主要爲後續關聯映射提供,避免查找無用的關聯數據。
- 可以降低數據庫操作的併發率,提升內存資源使用率
緩存
1. 一級緩存(默認開啓)
每個Session對象創建出來,就會分配一塊緩存空間,可以存儲session對象訪問的對象信息。session關閉後會自動清除緩存,手動清除可以session.clear(),session.evict(obj)。Session一級緩存是獨享。
load/get/save/update/saveorupdate方法處理的對象都會放入緩存中
優點:可以減少查詢數據庫的次數,加快查詢速度。 缺點:在批量操作中容易導致內存溢出問題。
public void batch(){
// ... 開啓事務
for(int i=1;i<100000;i++){
session.save(dept);
if(i%100==0){
//提交一次,把緩存清空下
session.flush();
session.clear();
}
}
// ... 提交事務
}
2. 二級緩存(關閉)
SessionFactory對象緩存,可以被創建出的多個Session對象共享。
二級緩存開啓過程:
- 導入ehcache工具包和ehcache.xml配置文件
在hibernate.cfg.xml中配置參數開啓二級緩存,啓用ehcache
<property
name=”hibernate.cache.use_sencond_level_cache”>true
org.hibernate.cache.ehcache.EhCacheRegionFactory- 在要緩存的對象類型中,指定@Cache註解標記
@Entity
@Table(name="DEPT") @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Dept implements Serializable{
//... ... }
通過上面步驟,Dept對象可以採用二級緩存存儲。 注意 :session對象要源於同一個sessionfactory.
3. 查詢緩存(關閉)
一級和二級緩存,只能緩存單個對象,如果需要緩存一個結果集,必須使用查詢緩存。
查詢緩存開啓過程:
- 針對於對象要開啓二級緩存
- 在hibernate.cfg.xml中開啓查詢緩存
<property name="hibernate.cache.use_query_cache">true</property>
- 在查詢執行前,調用query.setCacheable(true);
持久化
- Hibernate框架可以構建一個持久層。持久層是由持久對象構成。
- 持久對象:指的是具有持久性的數據對象。
- 持久性是指當對象數據狀態發生改變後,可以與數據庫同步。
- 持久對象都存儲在一級/二級緩存中
Hibernate有什麼缺點
1.HQL最終還是要轉換爲JDBC,效率降低;
2.Hibernate對JDBC封裝的過於厲害。所有失去了對SQL的控制
3.不適合系統中複雜的關聯查詢,包括多表、複雜查詢、大量數據的查詢處理都不好。
4.數據量較大時,緩存機制不好使,效率明顯降低;
5.對於大批量數據的修改、刪除,不適合用Hibernate,這也是ORM框架的弱點。
6.對吸納規劃限制我們的查詢。例如,一個持久性類不能映射到多個表。
7.Hibernate帶來方便的同時,也使得程序出錯排查非常困難。
8.Hibernate是完善的ORM框架,想要Hibernate工作好,數據庫設計必須好。數據庫結構的變更,需要修改hbm和bean,Hibernate自適應能力爲0.
9.setter方法的參數需要自己轉換類型。
如何優化Hibernate
1.使用雙向一對多關聯,不使用單向一對多。
2.靈活使用單向一對多關聯。
3.不用一對一,用多對一取代。
4.配飾對象緩存,不使用集合緩存。
5.一對多集合使用bag,多對多集合使用set;
6.繼承類使用顯示多態。
7.表字段要少,表關聯不要怕多,有二級緩存撐腰。
Hibernate是如何延遲加載
1.Hibernate2延遲加載實現:a)實體對象b)集合(Collection );
2.Hibernate3提供了屬性的延遲加載功能;
當Hibernate在查詢數據的時候,數據並沒有存放在內存中,當程序真正對數據操作時,對象才存放在內存中,就實現了延遲加載,他苷省了服務器的內存開銷,從而提高了服
務器的性能。
Hibernate有以下五個核心接口:
1.Configuration負責加載主配置文件信息,同時也加載映射關係文件信息。
2.SessionFactory 負責創建Session對象。
3.Session數據庫連接會話,負責執行增刪改操作。
4.Transaction負責事務控制。
5.Query負責執行特殊査詢。
簡要描述對對象關係映射(object-relational mapping。簡稱ORM)的理解,並說明經典實現框架。
對象關係映射(Object-Relational Mapping ,簡稱ORM)是一種爲了解決面向對象與面向關係數據庫存在的互不匹配的現象的技術;簡單的說,ORM是通過使用描述對象和數據庫之間映射的元數據,將java程序中的對象自動持久化到關係數據庫中;本質上就是將數據從一種形式轉換到另外種形式。
經典的ORM實現框架有Hibernate和Mybatis。
簡單說說session.load()和session.get()的區別,哪種方式可以使用二級緩存
session.load()和session.get()的區別爲:
1.get不支持延遲加載,而load支持。換句話說,get方法一定獲取實際的對象, 而load有可能返回代理對象。
2.如果未能發現符合條件的記錄,get方法返回null,而load方法會拋出一個 ObjectNotFoundException。 get方法和load方法都可以使用二級緩存。
Hibernate中對象有哪幾種狀態,有什麼規則?
Hibernate中對象可以看做有3種狀態,分別是臨時態、持久態、遊離態,這些狀態可以相互轉換,轉換規則如下圖:
具體各個狀態的特徵爲:
1.臨時態
1)臨時態的對象可以被垃圾回收;
2)臨時態的對象未進行過持久化未與session關聯。
2.持久態
1)持久態對象垃圾回收器不能回收;
2)持久態的對象進行了持久化,與session相關聯,即持久態對象存在於session 緩存中,由session負責管理。
3)持久態對象的數據可以自動更新到數據庫中,時機是在調用session.flushO時執 行。而提交事務時會調用session.flushO ,因此提交事務時也會觸發同步,可以理解爲 tsxommit=sessionilush()+commit。
3.遊離態
1)遊離態的對象可以被垃圾回收;
2)遊離態的對象進行過持久化,但已與session解除了關聯。
Hibernate中的關聯映射有如下幾種:
1)—對一關聯
2)—對多關聯
3)多對一關聯
4)多對多關聯
Hibernate有哪幾種查詢方式
1)使用API查詢,如get、load
2)使用HQL查旬
3)使用SQL査詢
4 )使用Criteria査詢
請簡述Hibernate一級緩存和二級緩存的區別和聯繫?
—級緩存是Session級別的緩存,由Session負責管理,因此一級緩存是Session獨享的,即每個Session只能訪問自己的一級緩存區。
二級緩存是SessionFactory級別的緩存,由SessionFactory負責管理,因此二級緩 存是Session間共享的,即不同的Session都可以訪問二級緩存區。
一級緩存和二級緩存相同的地方是,他們緩存的都是對象數據。