Hibernate是一個開源的ORM(對象關係映射)框架,是對JDBC的進一步封裝。
1、Configuration接口:負責配置並啓動Hibernate,SessionFactory創建完成它就被丟棄。
Configuration對象用於配置並根啓動Hibernate。Hibernate應用通過Configuration實例來指定對象—關係映射文件的位置或者動態配置Hibernate的屬性,然後創建SessionFactory實例。我們可以查看Configuration的源代碼,它的configure()方法是這樣實現的:
public Configuration configure() throwsHibernateException {
configure("/hibernate.cfg.xml" );//此處指定了ORM文件的位置
return this;
}
我們看到它是在這裏指定了ORM文件的位置,這就是爲什麼Hibernate總是默認到classpath下去尋找hibernate.cfg.xml文件的原因了。實際上我們還可以通過configure(String resource)來動態的指定配置文件,只不過通常我們都是採用的默認設置罷了。這樣的話我們的配置文件就都被讀取了,同時配置文件中通過<mapping>元素引入的映射文件也被讀取了。
2、SessionFactory接口:負責初始化Hibernate
SessionFactroy接口負責初始化Hibernate。它充當數據存儲源的代理,並負責創建Session對象。這裏用到了工廠模式。需要注意的是SessionFactory並不是輕量級的,因爲一般情況下,一個項目通常只需要一個SessionFactory就夠,當需要操作多個數據庫時,可以爲每個數據庫指定一個SessionFactory。
3、Session接口:負責持久化對象的CRUD操作
Session接口 Session 接口對於Hibernate 開發人員來說是一個最重要的接口。然而在Hibernate中,實例化的Session是一個輕量級的類,創建和銷燬它都不會佔用很多資源。這在實際項目中確實很重要,因爲在客戶程序中,可能會不斷地創建以及銷燬Session對象,如果Session 的開銷太大,會給系統帶來不良影響。但是Session對象是非線程安全的,因此在你的設計中,最好是一個線程只創建一個Session對象。 session可以看作介於數據連接與事務管理一種中間接口。我們可以將session想象成一個持久對象的緩衝區,Hibernate能檢測到這些持久對象的改變,並及時刷新數據庫。我們有時也稱Session是一個持久層管理器,因爲它包含這一些持久層相關的操作, 諸如存儲持久對象至數據庫,以及從數據庫從獲得它們。需要注意的是,Hibernate的session不同於JSP 應用中的HttpSession。當我們使用session這個術語時,我們指的Hibernate 中的session,而我們以後會將HttpSesion 對象稱爲用戶session。
4、Transaction接口:負責事務
Transaction接口負責事務相關的操作,一般在Hibernate的增刪改中出現,但是使用Hibernate的人一般使用Spring去管理事務。
5、Query接口和Criteria接口:負責執行各種數據庫查詢
Query負責執行各種數據庫查詢。它可以使用HQL語言或SQL語句兩種表達方式。它的返回值一般是List。需要自己轉換。
Hibernate有四種查詢方案
1、get,load方法,根據id查找對象
2、HQL--hibernate query language(查詢對象:Query)
3、Criteria--標準查詢語言(查詢對象:Criteria,查詢條件:Criterion)
4、通過sql來查(查詢對象:SQLQuery)
具體
Query/Criteria:
1.Query接口封裝了Hibernate強大的對象查詢能力,同時也支持數據庫的更新操作
2.提供了動態查詢的參數綁定功能
3.提供list(),iterator(),scroll()等對象導航方法
4.提供uiqueResult()方法獲取單獨的對象
5.提供executeUpdate()方法來執行DML語句
6.提供了可移植的分頁查詢方法
Session:
1、save,presist保存數據,persist在事務外不會產生insert語句。
2、delete,刪除對象
3、update,更新對象,如果數據庫中沒有記錄,會出現異常,脫管對象如屬性改變需要保存,則調用update方法
4、get,根據ID查,會立刻訪問數據庫
5、load,根據ID查,(返回的是代理,不會立即訪問數據庫)
6、saveOrUpdate,merge(根據ID和version的值來確定是否是save或update),調用merge你的對象還是託管的。當不知該對象的狀態時可調用該方法
小貼士:瞬時對象id無值,脫管對象有值,hibernate通過該方式判斷對象的狀態
7、lock(把對象變成持久對象,但不會同步對象的狀態)
Hibernate運行過程:
1.通過Configuration().configure();讀取並解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的<mappingresource="com/xx/User.hbm.xml"/>讀取並解析映射信息
3.通過config.buildSessionFactory();//創建SessionFactory
4.sessionFactory.openSession();//打開Sesssion
5.session.beginTransaction();//創建事務Transation
6.persistent operate持久化操作 //一般指Save這個方法
7.session.getTransaction().commit();//提交事務
8.關閉Session
9.關閉SesstionFactory
Hibernate優缺點:
優點:
1、更加對象化
以對象化的思維操作數據庫,我們只需要操作對象就可以了,開發更加對象化。
2、移植性
因爲Hibernate做了持久層的封裝,你就不知道數據庫,你寫的所有的代碼都具有可複用性。
3、Hibernate是一個沒有侵入性的框架,沒有侵入性的框架我們稱爲輕量級框架。
對比Struts的Action和ActionForm,都需要繼承,離不開Struts。Hibernate不需要繼承任何類,不需要實現任何接口。這樣的對象叫POJO對象。
4、Hibernate代碼測試方便。
5、提高效率,提高生產力。
缺點:
1、使用數據庫特性的語句,將很難調優
2、對大批量數據更新存在問題
3、系統中存在大量的攻擊查詢功能
參考文章: Hibernate之底層原理的7點整理和總結
1.什麼是hibernate 方言,如何配置方言?
通常我們會在hibernate.cfg.xml文件中這樣配置:
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
那爲什麼要配置方言呢?
答:
Hibernate底層依然使用SQL語句來執行數據庫操作,雖然所有關係型數據庫都支持使用標準SQL語句,但所有數據庫都對標準SQL進行了一些擴展,所以在語法細節上存在一些差異,因此Hibernate需要根據數據庫來識別這些差異。
舉例來說,我們在MySQL數據庫裏進行分頁查詢,只需使用limit關鍵字就可以了;而標準SQL並不支持limit關鍵字,例如Oracle則需要使用行內視圖的方式來進行分頁。同樣的應用程序,當我們在不同數據庫之間遷移時,底層數據庫的訪問細節會發生改變,而Hibernate也爲這種改變做好了準備,現在我們需要做的是:告訴Hibernate應用程序的底層即將使用哪種數據庫——這就是數據庫方言。
一旦我們爲Hibernate設置了合適的數據庫方言,Hibernate將可以自動應付底層數據庫訪問所存在的細節差異。
以下提供一個方言配置表供參考:
RDBMS | 方言 |
---|---|
DB2 | org.hibernate.dialect.DB2Dialect |
DB2 AS/400 | org.hibernate.dialect.DB2400Dialect |
DB2 OS390 | org.hibernate.dialect.DB2390Dialect |
PostgreSQL | org.hibernate.dialect.PostgreSQLDialect |
MySQL | org.hibernate.dialect.MySQLDialect |
MySQL with InnoDB | org.hibernate.dialect.MySQLInnoDBDialect |
MySQL with MyISAM | org.hibernate.dialect.MySQLMyISAMDialect |
Oracle (any version) | org.hibernate.dialect.OracleDialect |
Oracle 9i/10g | org.hibernate.dialect.Oracle9Dialect |
Sybase | org.hibernate.dialect.SybaseDialect |
Sybase Anywhere | org.hibernate.dialect.SybaseAnywhereDialect |
Microsoft SQL Server | org.hibernate.dialect.SQLServerDialect |
SAP DB | org.hibernate.dialect.SAPDBDialect |
Informix | org.hibernate.dialect.InformixDialect |
HypersonicSQL | org.hibernate.dialect.HSQLDialect |
Ingres | org.hibernate.dialect.IngresDialect |
Progress | org.hibernate.dialect.ProgressDialect |
Mckoi SQL | org.hibernate.dialect.MckoiDialect |
Interbase | org.hibernate.dialect.InterbaseDialect |
Pointbase | org.hibernate.dialect.PointbaseDialect |
FrontBase | org.hibernate.dialect.FrontbaseDialect |
Firebird | org.hibernate.dialect.FirebirdDialect |
2. Hibernate中的Session指的是什麼? 可否將單個的Session在多個線程間進行共享?
Session代表着Hibernate所做的一小部分工作,它負責維護者同數據庫的鏈接而且 不是線程安全的,也就是說,Hibernage中的Session不能在多個線程間進行共享。雖然Session會以主動滯後的方式獲得數據庫連接,但是Session最好還是在用完之後立即將其關閉。
3. hibernate中sorted collection和ordered collection有什麼不同?
sorted collection是通過使用 Java的Comparator在內存中進行排序的,ordered collection中的排序用的是數據庫的order by子句。對於比較大的數據集,爲了避免在內存中對它們進行排序而出現 Java中的OutOfMemoryError,最好使用ordered collection。
4. Hibernate中transient、persistent、detached對象三者之間有什麼區別?
對象具有三種狀態:transient、persistent和detached。同Hibernate的session有關聯的對象是persistent對象。對這種對象進行的所有修改都會按照事先設定的刷新策略,反映到數據庫之中,也即,可以在對象的任何一個屬性發生改變時自動刷新,也可以通過調用Session.flush()方法顯式地進行刷新。如果一個對象原來同Session有關聯關係,但當下卻沒有關聯關係了,這樣的對象就是detached的對象。你可以通過調用任意一個session的update()或者saveOrUpdate()方法,重新將該detached對象同相應的seesion建立關聯關係。Transient對象指的是新建的持久化類的實例,它還從未同Hibernate的任何Session有過關聯關係。同樣的,你可以調用persist()或者save()方法,將transient對象變成persistent對象。可要記住,這裏所說的transient指的可不是 Java中的transient關鍵字,二者風馬牛不相及。
5. Hibernate中Session的lock()方法有什麼作用?
因爲Session的lock()方法重建了關聯關係卻並沒有同數據庫進行同步和更新。因此,你在使用lock()方法時一定要多加小心。順便說一下,在進行關聯關係重建時,你可以隨時使用Session的update()方法同數據庫進行同步。有時這個問題也可以這麼來問:Session的lock()方法和update()方法之間有什麼區別?。這個小節中的關鍵點也可以拿來回答這個問題。
6. Hibernate中二級緩存指的是什麼?
二級緩存是在SessionFactory這個級別維護的緩存,它能夠通過節省幾番數據庫調用往返來提高性能。還有一點值得注意,二級緩存是針對整個應用而不是某個特定的session的。
7. Hibernate中的查詢緩存指的是什麼?
查詢緩存實際上保存的是sql查詢的結果,這樣再進行相同的sql查詢就可以之間從緩存中拿到結果了。爲了改善性能,查詢緩存可以同二級緩存一起來使用。Hibernate支持用多種不同的開源緩存方案,比如EhCache,來實現查詢緩存。
8. 爲什麼在Hibernate的實體類中要提供一個無參數的構造器?
每個Hibernate實體類必須包含一個 無參數的構造器, 這是因爲Hibernate框架要使用Reflection API,通過調用Class.newInstance()來創建這些實體類的實例。如果在實體類中找不到無參數的構造器,這個方法就會拋出一個InstantiationException異常。
9. 可不可以將Hibernate的實體類定義爲final類?
是的,你可以將Hibernate的實體類定義爲final類,但這種做法並不好。因爲Hibernate會使用代理模式在延遲關聯的情況下提高性能,如果你把實體類定義成final類之後,因爲 Java不允許對final類進行擴展,所以Hibernate就無法再使用代理了,如此一來就限制了使用可以提升性能的手段。不過,如果你的持久化類實現了一個接口而且在該接口中聲明瞭所有定義於實體類中的所有public的方法輪到話,你就能夠避免出現前面所說的不利後果。
SpringMVC+Spring+Hibernate整合參照:框架篇:Spring+SpringMVC+hibernate整合開發