一、Hibernate:ORM(Object Relation Mapping)對象關系映射框架
常用的ORM框架有:Hibernate、TopLink、OJB。
Hibernate 框架完全是進行對象的操作,不再會有對字段、屬性的操作。如Hibernate 刪除則是刪除一個對象,更新則是對某一個對象狀態進行更新
小貼士:應用Hibernate開發時,可與JDBC相聯想
二、開發流程:
1.由Domain Object ----》mapping -----》db(官方推薦)
2.由DB開始,用工具生成mapping和Domain Object(使用較多)
3.由映射文件開始
Domain Object 限制:
1.默認的構造方法(必須的)
2.有無意義的標示符id(主鍵)(可選)
3.非final,對懶加載有影響
三、需要一個工具類,只加載一次 hibernate.cfg.xml 文件
package cn.itcast.hibernate;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;


publicfinalclass HibernateUtil
{


private HibernateUtil()
{}

privatestatic SessionFactory sf = null;


static
{

Configuration cfg = new Configuration();

cfg.configure();

//cfg.configure(new File("filename")); //指定配置文件的路徑,不指定則默認

sf = cfg.buildSessionFactory();

}


publicstatic SessionFactory getSessionFactory()
{

returnsf;

}


publicstatic Session getSession()
{

returnsf.openSession();

}

}

小貼士:將java類與hibernate源碼綁定
四、Mysql 有多種引擎:
MyISAM:5.0以前的缺省引擎,效率高但不支持事務。
InnoDB:支持事務,則Hibernate操作時需要開啟事務,進行操作后提交事務,這樣才能將數據持久化:
Transaction tx = s.beginTransaction();//開啟事務
User user = new User();
user.setName("name");
user.setBirthday(new Date());
s.save(user);
tx.commit(); //事務提交
五、Hibernate 核心接口概述:
Configuration:
負責管理Hibernate的配置信息,這些信息由配置文件提供,包括如下內容:
1.Hibernate運行的底層信息:數據庫的URL、用戶名、密碼、JDBC驅動類等,數據庫Dialect,數據庫連接池等。
2.Hibernate映射文件(*.hbm.xml)
調用代碼:
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.應用程序從SessionFactory(會話工廠)里獲得Session(會話)實例。它在多個應用線程間進行共享。通常情況下,整個應用只有唯一的一個會話工廠---例如在應用初始化時被創建。然而,如果你使用Hibernate訪問多個數據庫,你需要每個數據庫使用一個會話工廠。
2.會話工廠緩存了生成的SQL語句和Hibernate在運行時使用的映射元數據。
3.調用代碼:
privatestatic SessionFactory sf = null;
static {
Configuration cfg = new Configuration();
cfg.configure();
sf = cfg.buildSessionFactory();
}
Session:
1.Session不是線程安全的,它代表與數據庫之間的一次操作會話
2.Session也稱為持久化管理器,因為它是與持久化有關的操作接口
3.Session通過SessionFactory打開,在所有的工作完成后,需要關閉
4.Session緩存其管理的持久化對象
5.調用代碼:
Session session sessionFactory.openSession();
Transaction:
1.它將應用代碼從底層的事務實現中抽象出來---這可能是一個JDBC事務,一個JTA用戶事務或者甚至是一個公共對象請求代碼結構(CORBA)---允許應用通過一組一致的API控制事務邊界
2.這有助于保持Hibernate應用在不同類型的執行環境或容器中的可移植性
3.Hibernate提供的事務提交模式默認為非自動提交模式(默認:autoCommit=false),因此使用Hibernate進行操作時(增、刪、改)必須顯示的調用Transaction的API
4.調用代碼:
Transaction tx = session.beginTransction();
Tx.commit()/rollback();
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中對象的狀態:
狀態的參考:數據庫中是否有記錄;是否有session關聯
1、瞬時(transient):數據庫中沒有數據與之對應,超過作用域被JVM垃圾回收器回收,一般是new出來且session沒有關聯的對象
2、持久(persistent):數據庫中有數據與之對應,當前session有關聯,并且相關聯的session沒有關閉,事務沒有提交;持久對象狀態發生改變,在事務提交時會影響到數據庫(hibernate能檢測到)
3、脫管(detached):數據庫中有數據與之對應,但當前沒有session與之關聯;托管對象狀態發生改變,hibernate不能檢測到
對象在的狀態轉化:


當對象被save,commit后,Hibernate Session 任然能察覺到對象,如果此時對象屬性發生改變,則數據庫中持久化的值同樣被改變,如:
//標準方法
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對象在數據庫中最終持久化的name=="new name",如果在commit之前修改過的屬性,將會在commit時候統一對對象進行update。
七、Hibernate Query Language(HQL)和Criteria(QBC)
HQL:面向對象的查詢語言,與SQL不同,HQL中的對象名是區分大小寫的(除了JAVA類和屬性其他部分不區分大小寫);HQL中查的是對象而不是和表,并且支持多態;HQL主要通過Query來操作,Query的創建方式:
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 ... 因為HQL支持多態,所以執行 from Object時,將會將所有的表都查一遍
/**
* 當查詢條件有多個的時候,則參數 "?" 將會有多個,這樣對我們的維護帶來極大不便,在HQL中我們利用命名參數處理
* "from User as user where user.name=?" -->> "from User as user where user.name=:n"
* query.setString("n", name);
* 經過這樣設置后在多條件情況下,我們不需要再顧及參數的先后順序了
*/
Query query = s.createQuery(hql);
query.setString(0, name);
/**
* Hibernate 分頁: 200-210 條
* query.setFirstResults(200);
* query.setMaxResults(10);
* 這樣的分頁,為數據庫的移植做到了很好的兼容,根據數據庫設置的方言來判斷
*/
List<User> list = query.list();
//Object obj = query.uniqueResult(); 當我們確定返回的結果集就一條記錄,則可調用此方法,如有多條,則會報異常
for(User user : list) {
System.out.println(user.getName());
}
} finally {
if (s != null) {
s.close();
}
}
}
HQL 跟SQL 查詢的區別:
HQL根據屬性名查對象,SQL根據字段查表
Creteria:Criteria是一種比HQL更面向對象的條件查詢方式;Criteria的創建方式:
Criteria crit = session.createCrieria(DomainClass.class);
簡單屬性條件如:
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); //對User進行約束查詢
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的異??梢圆蝗ゲ僮?,因為事務收不到commit事務就會回滾
八、對象關系的關聯映射
1.多對一(Employee - Department) --- 最常用
2.一對多(Department - Employee)
3.一對一(Person - IdCard)
4.多對多(Teacher - Student) -- 需要建立中間表
在操作和性能方面都不太理想,所以多對多的映射,實際使用中最好轉換成一對多的對象模型;Hibernate會為我們創建中間關聯表,轉換成兩個一對多。
<set name="teacher" table="teacher_student">
<key column="teacher_id"/>
<many-to-many class="Student" column="student_id"/>
</set>
5.組件映射(User - Name)
關聯的屬性是個復雜類型的持久化類,但不是實體,即:數據庫中沒有表與該屬性對應,但該類的屬性要永久保存的。
<component name="name" class="com.test.hibernate.domain.Name">
<property name="initial" />
<property name="first" />
<property name="last" />
</component>
當組件的屬性不能和表中的字段簡單對應的時候可以選擇實現:
org.hibernate.usertype.UserType or
org.hibernate.usertype.CompositeUserType
6.集合映射(set,list,map,bag)
絕大部分使用set
如果習慣使用list,又不想讓Hibernate維護順序,對象里用List,映射時用bag
映射用list比bag少
鍵值對方式用map
數組因為對元素變化應用不方便
<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() //保存對象
a) 把臨時對象加載到緩存中,使之成為持久化對象
b) 使用指定的ID生成器為持久化對象分配OID
c) 當對象處于持久化狀態Hibernate不允許修改其IOD
2.update() //修改對象
a) 把游離對象加入到緩存中,使一個游離對象變成持久化對象
b) 計劃執行update SQL語句,根據對象IOD來更新對象所對應的數據
c) Update不能更新一個在session中已經關聯的相同OID的對象
3.saveOrUpdate() //保存或修改對象
a) 同時包含save和update方法的功能,根據對象的狀態自動執行相應的功能
b) 若對象為臨時狀態則執行save,若為游離狀態則執行update方法
4.merge()//合并對象
a) 直接修改表中的記錄,并不影響該對象原來的狀態
5.delete() //刪除指定的對象
a) 如果是持久態對象,就計劃執行delete語句
b) 如果是游離狀態的對象,先使用游離對象被session緩存關聯,變成持久化對象,再計劃執行delete語句
5.contains() //判斷實體對象是否與session關聯
a) 可以用此方法判斷對象是否處于持久化狀態
6.evict() //把實體對象從緩存中移除
7.clear() //清除session緩存中所有持久化對象
8.get/load 方法區別:
a) 都是根據OID從數據庫中加載一個持久化對象
b) 當數據庫中不存在與OID對象的記錄時,get()返回一個null引用,而load則會拋出ObjectNotFoundException異常
c) Load方法可以返回一個實體的代理類實例,而get方法只是直接返回實體類對象