Hibernate 主要知識(shí)點(diǎn)的歸納
Posted on 2010-05-27 01:11 Gavin.lee 閱讀(1330) 評(píng)論(0) 編輯 收藏 所屬分類: SSH2 --Hibernate一、Hibernate:ORM(Object Relation Mapping)對(duì)象關(guān)系映射框架
常用的ORM框架有:Hibernate、TopLink、OJB。
Hibernate 框架完全是進(jìn)行對(duì)象的操作,不再會(huì)有對(duì)字段、屬性的操作。如Hibernate 刪除則是刪除一個(gè)對(duì)象,更新則是對(duì)某一個(gè)對(duì)象狀態(tài)進(jìn)行更新
小貼士:應(yīng)用Hibernate開發(fā)時(shí),可與JDBC相聯(lián)想
二、開發(fā)流程:
1.由Domain Object ----》mapping -----》db(官方推薦)
2.由DB開始,用工具生成mapping和Domain Object(使用較多)
3.由映射文件開始
Domain Object 限制:
1.默認(rèn)的構(gòu)造方法(必須的)
2.有無意義的標(biāo)示符id(主鍵)(可選)
3.非final,對(duì)懶加載有影響
三、需要一個(gè)工具類,只加載一次 hibernate.cfg.xml 文件








































小貼士:將java類與hibernate源碼綁定
四、Mysql 有多種引擎:
MyISAM:5.0以前的缺省引擎,效率高但不支持事務(wù)。
InnoDB:支持事務(wù),則Hibernate操作時(shí)需要開啟事務(wù),進(jìn)行操作后提交事務(wù),這樣才能將數(shù)據(jù)持久化:
Transaction tx = s.beginTransaction();//開啟事務(wù)
User user = new User();
user.setName("name");
user.setBirthday(new Date());
s.save(user);
tx.commit(); //事務(wù)提交
五、Hibernate 核心接口概述:
Configuration:
負(fù)責(zé)管理Hibernate的配置信息,這些信息由配置文件提供,包括如下內(nèi)容:
1.Hibernate運(yùn)行的底層信息:數(shù)據(jù)庫的URL、用戶名、密碼、JDBC驅(qū)動(dòng)類等,數(shù)據(jù)庫Dialect,數(shù)據(jù)庫連接池等。
2.Hibernate映射文件(*.hbm.xml)
調(diào)用代碼:
1.屬性文件(hibernate.properties)
Configuration cfg = new Configuration();
cfg.addClass(XXX.class);//該方法加載XXX.hbm.xml
cfg.addResource();
2.XML文件(hibernate.cfg.xml)
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory:
1.應(yīng)用程序從SessionFactory(會(huì)話工廠)里獲得Session(會(huì)話)實(shí)例。它在多個(gè)應(yīng)用線程間進(jìn)行共享。通常情況下,整個(gè)應(yīng)用只有唯一的一個(gè)會(huì)話工廠---例如在應(yīng)用初始化時(shí)被創(chuàng)建。然而,如果你使用Hibernate訪問多個(gè)數(shù)據(jù)庫,你需要每個(gè)數(shù)據(jù)庫使用一個(gè)會(huì)話工廠。
2.會(huì)話工廠緩存了生成的SQL語句和Hibernate在運(yùn)行時(shí)使用的映射元數(shù)據(jù)。
3.調(diào)用代碼:
privatestatic SessionFactory sf = null;
static {
Configuration cfg = new Configuration();
cfg.configure();
sf = cfg.buildSessionFactory();
}
Session:
1.Session不是線程安全的,它代表與數(shù)據(jù)庫之間的一次操作會(huì)話
2.Session也稱為持久化管理器,因?yàn)樗桥c持久化有關(guān)的操作接口
3.Session通過SessionFactory打開,在所有的工作完成后,需要關(guān)閉
4.Session緩存其管理的持久化對(duì)象
5.調(diào)用代碼:
Session session sessionFactory.openSession();
Transaction:
1.它將應(yīng)用代碼從底層的事務(wù)實(shí)現(xiàn)中抽象出來---這可能是一個(gè)JDBC事務(wù),一個(gè)JTA用戶事務(wù)或者甚至是一個(gè)公共對(duì)象請(qǐng)求代碼結(jié)構(gòu)(CORBA)---允許應(yīng)用通過一組一致的API控制事務(wù)邊界
2.這有助于保持Hibernate應(yīng)用在不同類型的執(zhí)行環(huán)境或容器中的可移植性
3.Hibernate提供的事務(wù)提交模式默認(rèn)為非自動(dòng)提交模式(默認(rèn):autoCommit=false),因此使用Hibernate進(jìn)行操作時(shí)(增、刪、改)必須顯示的調(diào)用Transaction的API
4.調(diào)用代碼:
Transaction tx = session.beginTransction();
Tx.commit()/rollback();
Query/Criteria:
1.Query接口封裝了Hibernate強(qiáng)大的對(duì)象查詢能力,同時(shí)也支持?jǐn)?shù)據(jù)庫的更新操作
2.提供了動(dòng)態(tài)查詢的參數(shù)綁定功能
3.提供list(),iterator(),scroll()等對(duì)象導(dǎo)航方法
4.提供uiqueResult()方法獲取單獨(dú)的對(duì)象
5.提供executeUpdate()方法來執(zhí)行DML語句
6.提供了可移植的分頁查詢方法
Session:
1、save,presist保存數(shù)據(jù),persist在事務(wù)外不會(huì)產(chǎn)生insert語句。
2、delete,刪除對(duì)象
3、update,更新對(duì)象,如果數(shù)據(jù)庫中沒有記錄,會(huì)出現(xiàn)異常,脫管對(duì)象如屬性改變需要保存,則調(diào)用update方法
4、get,根據(jù)ID查,會(huì)立刻訪問數(shù)據(jù)庫
5、load,根據(jù)ID查,(返回的是代理,不會(huì)立即訪問數(shù)據(jù)庫)
6、saveOrUpdate,merge(根據(jù)ID和version的值來確定是否是save或update),調(diào)用merge你的對(duì)象還是托管的。當(dāng)不知該對(duì)象的狀態(tài)時(shí)可調(diào)用該方法
小貼士:瞬時(shí)對(duì)象id無值,脫管對(duì)象有值,hibernate通過該方式判斷對(duì)象的狀態(tài)
7、lock(把對(duì)象變成持久對(duì)象,但不會(huì)同步對(duì)象的狀態(tài))
六、Hibernate中對(duì)象的狀態(tài):
狀態(tài)的參考:數(shù)據(jù)庫中是否有記錄;是否有session關(guān)聯(lián)
1、瞬時(shí)(transient):數(shù)據(jù)庫中沒有數(shù)據(jù)與之對(duì)應(yīng),超過作用域被JVM垃圾回收器回收,一般是new出來且session沒有關(guān)聯(lián)的對(duì)象
2、持久(persistent):數(shù)據(jù)庫中有數(shù)據(jù)與之對(duì)應(yīng),當(dāng)前session有關(guān)聯(lián),并且相關(guān)聯(lián)的session沒有關(guān)閉,事務(wù)沒有提交;持久對(duì)象狀態(tài)發(fā)生改變,在事務(wù)提交時(shí)會(huì)影響到數(shù)據(jù)庫(hibernate能檢測(cè)到)
3、脫管(detached):數(shù)據(jù)庫中有數(shù)據(jù)與之對(duì)應(yīng),但當(dāng)前沒有session與之關(guān)聯(lián);托管對(duì)象狀態(tài)發(fā)生改變,hibernate不能檢測(cè)到
對(duì)象在的狀態(tài)轉(zhuǎn)化:
當(dāng)對(duì)象被save,commit后,Hibernate Session 任然能察覺到對(duì)象,如果此時(shí)對(duì)象屬性發(fā)生改變,則數(shù)據(jù)庫中持久化的值同樣被改變,如:
//標(biāo)準(zhǔn)方法
static void addUser(User user) {
Session s = null;
Transaction tx = null;
try {
s = HibernateUtil.getSession();
tx = s.beginTransaction();
s.save(user);
user.setName("new name");
tx.commit();
} catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
throw e;
} finally {
if (s != null)
s.close();
}
}
該user對(duì)象在數(shù)據(jù)庫中最終持久化的name=="new name",如果在commit之前修改過的屬性,將會(huì)在commit時(shí)候統(tǒng)一對(duì)對(duì)象進(jìn)行update。
七、Hibernate Query Language(HQL)和Criteria(QBC)
HQL:面向?qū)ο蟮牟樵冋Z言,與SQL不同,HQL中的對(duì)象名是區(qū)分大小寫的(除了JAVA類和屬性其他部分不區(qū)分大小寫);HQL中查的是對(duì)象而不是和表,并且支持多態(tài);HQL主要通過Query來操作,Query的創(chuàng)建方式:
Query q = session.createQuery(hql);
1.from Person
2.from User user where user.name=:name
3.from User user where user.name=:name and user.birthday<:birthday
static void query(String name) {
Session s = null;
try {
s = HibernateUtil.getSession();
String hql = "from User as user where user.name=?"; //from Object ... 因?yàn)镠QL支持多態(tài),所以執(zhí)行 from Object時(shí),將會(huì)將所有的表都查一遍
/**
* 當(dāng)查詢條件有多個(gè)的時(shí)候,則參數(shù) "?" 將會(huì)有多個(gè),這樣對(duì)我們的維護(hù)帶來極大不便,在HQL中我們利用命名參數(shù)處理
* "from User as user where user.name=?" -->> "from User as user where user.name=:n"
* query.setString("n", name);
* 經(jīng)過這樣設(shè)置后在多條件情況下,我們不需要再顧及參數(shù)的先后順序了
*/
Query query = s.createQuery(hql);
query.setString(0, name);
/**
* Hibernate 分頁: 200-210 條
* query.setFirstResults(200);
* query.setMaxResults(10);
* 這樣的分頁,為數(shù)據(jù)庫的移植做到了很好的兼容,根據(jù)數(shù)據(jù)庫設(shè)置的方言來判斷
*/
List<User> list = query.list();
//Object obj = query.uniqueResult(); 當(dāng)我們確定返回的結(jié)果集就一條記錄,則可調(diào)用此方法,如有多條,則會(huì)報(bào)異常
for(User user : list) {
System.out.println(user.getName());
}
} finally {
if (s != null) {
s.close();
}
}
}
HQL 跟SQL 查詢的區(qū)別:
HQL根據(jù)屬性名查對(duì)象,SQL根據(jù)字段查表
Creteria:Criteria是一種比HQL更面向?qū)ο蟮臈l件查詢方式;Criteria的創(chuàng)建方式:
Criteria crit = session.createCrieria(DomainClass.class);
簡(jiǎn)單屬性條件如:
criteria.add(Restrictions.eq(propertyName, value);
criteria.add(Restrictions.eqProperty(propertyName, otherPropertyName));
staticvoid cri(String name) {
Session s = null;
try {
s = HibernateUtil.getSession();
Criteria c = s.createCriteria(User.class); //對(duì)User進(jìn)行約束查詢
c.add(Restrictions.eq("name", name)); //添加約束條件
c.add(Restrictions.lt("birthday", new Date()));
/**
* Criteria 查詢同樣提供了分頁
*/
c.setFirstResult(200);
c.setMaxResults(210);
List<User> list = c.list();
for (User user : list) {
System.out.println(user.getName());
}
} finally {
if (s != null) {
s.close();
}
}
}
小貼士:1、官方推薦HQL 查詢
2、Hibernate try的異常可以不去操作,因?yàn)槭聞?wù)收不到commit事務(wù)就會(huì)回滾
八、對(duì)象關(guān)系的關(guān)聯(lián)映射
1.多對(duì)一(Employee - Department) --- 最常用
2.一對(duì)多(Department - Employee)
3.一對(duì)一(Person - IdCard)
4.多對(duì)多(Teacher - Student) -- 需要建立中間表
在操作和性能方面都不太理想,所以多對(duì)多的映射,實(shí)際使用中最好轉(zhuǎn)換成一對(duì)多的對(duì)象模型;Hibernate會(huì)為我們創(chuàng)建中間關(guān)聯(lián)表,轉(zhuǎn)換成兩個(gè)一對(duì)多。
<set name="teacher" table="teacher_student">
<key column="teacher_id"/>
<many-to-many class="Student" column="student_id"/>
</set>
5.組件映射(User - Name)
關(guān)聯(lián)的屬性是個(gè)復(fù)雜類型的持久化類,但不是實(shí)體,即:數(shù)據(jù)庫中沒有表與該屬性對(duì)應(yīng),但該類的屬性要永久保存的。
<component name="name" class="com.test.hibernate.domain.Name">
<property name="initial" />
<property name="first" />
<property name="last" />
</component>
當(dāng)組件的屬性不能和表中的字段簡(jiǎn)單對(duì)應(yīng)的時(shí)候可以選擇實(shí)現(xiàn):
org.hibernate.usertype.UserType or
org.hibernate.usertype.CompositeUserType
6.集合映射(set,list,map,bag)
絕大部分使用set
如果習(xí)慣使用list,又不想讓Hibernate維護(hù)順序,對(duì)象里用List,映射時(shí)用bag
映射用list比bag少
鍵值對(duì)方式用map
數(shù)組因?yàn)閷?duì)元素變化應(yīng)用不方便
<set name="employees">
<key column="depart_id" />
<one-to-many class="Employee" />
<!-- <element type="string" column="name" /> -->
<!--
<composite-element class="YourClass">
<property name="prop1" />
<property name="prop2" />
</composite>
-->
</set>
7.Inverse和cascade(Employee - Department)
九、映射文件剖析
1.hbm.cfg.xml
a)
2.Xxx.hbm.xml
a)
十、Hibernate的持久化操作
1.save() //保存對(duì)象
a) 把臨時(shí)對(duì)象加載到緩存中,使之成為持久化對(duì)象
b) 使用指定的ID生成器為持久化對(duì)象分配OID
c) 當(dāng)對(duì)象處于持久化狀態(tài)Hibernate不允許修改其IOD
2.update() //修改對(duì)象
a) 把游離對(duì)象加入到緩存中,使一個(gè)游離對(duì)象變成持久化對(duì)象
b) 計(jì)劃執(zhí)行update SQL語句,根據(jù)對(duì)象IOD來更新對(duì)象所對(duì)應(yīng)的數(shù)據(jù)
c) Update不能更新一個(gè)在session中已經(jīng)關(guān)聯(lián)的相同OID的對(duì)象
3.saveOrUpdate() //保存或修改對(duì)象
a) 同時(shí)包含save和update方法的功能,根據(jù)對(duì)象的狀態(tài)自動(dòng)執(zhí)行相應(yīng)的功能
b) 若對(duì)象為臨時(shí)狀態(tài)則執(zhí)行save,若為游離狀態(tài)則執(zhí)行update方法
4.merge()//合并對(duì)象
a) 直接修改表中的記錄,并不影響該對(duì)象原來的狀態(tài)
5.delete() //刪除指定的對(duì)象
a) 如果是持久態(tài)對(duì)象,就計(jì)劃執(zhí)行delete語句
b) 如果是游離狀態(tài)的對(duì)象,先使用游離對(duì)象被session緩存關(guān)聯(lián),變成持久化對(duì)象,再計(jì)劃執(zhí)行delete語句
5.contains() //判斷實(shí)體對(duì)象是否與session關(guān)聯(lián)
a) 可以用此方法判斷對(duì)象是否處于持久化狀態(tài)
6.evict() //把實(shí)體對(duì)象從緩存中移除
7.clear() //清除session緩存中所有持久化對(duì)象
8.get/load 方法區(qū)別:
a) 都是根據(jù)OID從數(shù)據(jù)庫中加載一個(gè)持久化對(duì)象
b) 當(dāng)數(shù)據(jù)庫中不存在與OID對(duì)象的記錄時(shí),get()返回一個(gè)null引用,而load則會(huì)拋出ObjectNotFoundException異常
c) Load方法可以返回一個(gè)實(shí)體的代理類實(shí)例,而get方法只是直接返回實(shí)體類對(duì)象