您好,登錄后才能下訂單哦!
使用Hibernate最大的目的就是對數(shù)據(jù)庫進(jìn)行crud操作。在講解之前,我們需要了解持久化以及持久化對象的三種狀態(tài)。
?
持久化就是把內(nèi)存中的數(shù)據(jù)永久的存儲到數(shù)據(jù)庫中
?
持久化類就是Java類與數(shù)據(jù)庫建立的一種映射關(guān)系,并把這個類稱做持久化類。實(shí)際上,就是一張數(shù)據(jù)表中的字段與類中的屬性字段相對象的類。
?
1.需要提供無參數(shù)的構(gòu)造方法
??因?yàn)镠ibernate通過反射機(jī)制生成類的實(shí)例
2.需要私有屬性,并提供對應(yīng)的get和set方法
??因?yàn)镠ibernate底層會對獲取到的數(shù)據(jù)驚醒封裝
3.屬性盡量使用包裝類類型
?? 區(qū)分空和null
4.類中必須存在一個唯一標(biāo)識 OID與表中的主鍵對應(yīng)
?? Hibernate利用這個這個唯一標(biāo)識來區(qū)分內(nèi)存中是否是同一個持久化類
5.不要使用final修飾類
??因?yàn)镠ibernate有加載延遲機(jī)制,這個機(jī)制會產(chǎn)生代理對象。代理對象是通過字節(jié) 碼增強(qiáng)技術(shù)來完成的,其實(shí)就是通過產(chǎn)生子類的方式,如果使用final修飾持久化類,這個機(jī)制就會失敗。加載延遲機(jī)制是一種優(yōu)化的手段。
?
主鍵的類型
- 自然主鍵
把具有業(yè)務(wù)含義的字段作為主鍵,稱為自然主鍵。比如,客戶的姓名(必須保證姓名不重復(fù),唯一,非空),這類主鍵往往會因?yàn)闃I(yè)務(wù)的改變重新設(shè)計(jì)表,造成數(shù)據(jù)庫維護(hù)困難。- 代理主鍵
把具有非業(yè)務(wù)字段作為主鍵,稱為代理主鍵。通常是ID,類型是整數(shù)類型(比字符串節(jié)省空間)- Hibernate提供了幾個內(nèi)置主鍵生成策略
1.increment:用于short int long類型。以自動增長的方式,每次增量是1。
2.identity:采用底層數(shù)據(jù)庫本身提供的主鍵生成標(biāo)識,前提是數(shù)據(jù)庫支持自動增長的類型。
3.sequence:Hibernate根基底層序列生成標(biāo)識符,前提是數(shù)據(jù)庫支持序列。
4.native:根據(jù)底層數(shù)據(jù)庫生成能力來判斷生成identity、sequence、hilo中的一種。適合跨數(shù)據(jù)庫開發(fā)。
5.uuid:采用128位uuid算法生成標(biāo)識符
6.assigned:由Java程序負(fù)責(zé)生成標(biāo)識符。如果不指定id的generator屬性,默認(rèn)使用該屬性。適合自然類型。
?
下面通過列舉例子來說明上述內(nèi)容
@Test
public void demo() {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 瞬時態(tài),此時沒有OID,也沒有與session關(guān)聯(lián)
User user = new User();
user.setUsername("robin");
Serializable save = session.save(user); // 持久態(tài)
transaction.commit();
session.close();
sessionFactory.close();
// 托管態(tài),此時session關(guān)閉,沒有與session關(guān)聯(lián),但是有OID
System.out.println(user);
}
轉(zhuǎn)換關(guān)系
?
瞬時態(tài)
1.瞬時態(tài) -- 持久態(tài)
??調(diào)用save()或者saveOrUpdate()
2.瞬時態(tài) -- 托管態(tài)
??為瞬時態(tài)添加 OID
?
持久態(tài):可以從Session get() load()方法獲取,或者Query對象等
1.持久態(tài) -- 瞬時態(tài)
??session.delete()刪除持久態(tài)化對象
2.持久態(tài) -- 托管態(tài)
??session.evict()、clear()、close()方法。evict()用于清除一級緩存中的某一個對象,clear()用于清除一級緩存中的所有對象, close()關(guān)閉session,并且清除一級緩存。
?
托管態(tài)
1.托管套 -- 持久態(tài)
??執(zhí)行update()、saveOrUpdate() lock()等
2,托管態(tài) -- 瞬時態(tài)
??把對象的OID設(shè)置為null
?
依賴Hibernateu一級緩存
@Test
public void demo() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
User user = session.get(User.class, 2);
user.setUsername("Robin");
// session.update(user); 這句話可以省略,因?yàn)槌志脩B(tài)的對象會自動更新數(shù)據(jù)庫
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
}
?
緩存是計(jì)算機(jī)為了提高讀取速度而設(shè)計(jì)的。通常介于應(yīng)用程序和永久性存儲介質(zhì)之間。提高應(yīng)用的運(yùn)行能力,通常是內(nèi)存。
?
Hibernate緩存分為一級緩存和二級緩存(redis替代),一級緩存是Hibernate內(nèi)置緩存,不能刪除。
?
Hibernate一級緩存實(shí)際上就是session緩存。Session緩存是一個內(nèi)存空間,存放相互管理的Java對象。在使用對象查找的時候,會使用OID在Hibernate一級緩存中進(jìn)行查找,如果查找到了,就返回此對象,否則,就會去數(shù)據(jù)庫查找與之相同OID的對象。
?
只要session實(shí)例沒有結(jié)束生命周期,存放在它上面的緩存也不會消失。
一級緩存的特點(diǎn)
當(dāng)應(yīng)用程序調(diào)用Session的save()、update、saveOrUpdate()的時候,Session緩存中沒有相應(yīng)的對象的時候,Hibernate會自動的從數(shù)據(jù)庫中提取對應(yīng)的數(shù)據(jù)加載到一級緩存中
當(dāng)應(yīng)用程序調(diào)用Session load()、get(),以及Query中的、list()、iterator()的時候,Hibernate首先會從以及緩存中尋找對象,如果存在則不需要去數(shù)據(jù)庫中查找。,如果沒有則從數(shù)據(jù)庫中獲取并加載到一級緩存中
當(dāng)調(diào)用Session.close()的時候,session緩存會被清空。
?
觀察控制臺輸出的SQL語句
@Test
public void demo() {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
/**
* 查詢兩次
*/
/**
* 第一次執(zhí)行你會查詢數(shù)據(jù)庫
* 第二次查詢只會去緩存中尋找
*/
User user = session.get(User.class, 1);
User user1 = session.get(User.class, 1);
transaction.commit();
session.close();
sessionFactory.close();
}
?
Hibernate向一級緩存中存儲數(shù)據(jù)的時候,會拷貝一份數(shù)據(jù)放在Hibernate快照區(qū),當(dāng)使用事務(wù)提交之后,會根據(jù)OID比較一級緩存中的數(shù)據(jù)和快照區(qū)中的數(shù)據(jù)是否一致,如果不一致,則執(zhí)行更新操作,并且同步快照區(qū)的數(shù)據(jù),否則則不執(zhí)行任何操作。
?
?
?
?
在業(yè)務(wù)層處理事務(wù)的方法
1.在業(yè)務(wù)層中獲取session,把它傳遞給持久層
2.使用ThreadLocal將業(yè)務(wù)層獲取到的session綁定到當(dāng)前線程中去。然后到業(yè)務(wù)層獲取的時候獲取當(dāng)前線程的session.
<property name="hibernate.current_session_context_class">thread</property>
sessionFactory.getCurrentSession()
可以不需要關(guān)閉session,線程結(jié)束之后會自動關(guān)閉
thread: Session對象的生命周期與本地線程綁定
jta:Session對象的生命周期與JTA事務(wù)綁定
managed:Hinernate委托程序來管理Session對象的生命周期
?
??
Query是面對對象的Hibernate查詢操作。通過session.createQuery(),傳遞一個HQL語句,獲取Query對象。
@Test
public void demo() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
/**
* 創(chuàng)建Query
* 調(diào)用對象的方法
*/
Query query = session.createQuery("from User");
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
Criteria是一個完全面對對象,可擴(kuò)展的條件查詢API,它不需要考慮數(shù)據(jù)庫底層的實(shí)現(xiàn),以及SQL語句的編寫。它是Hibernate核心查詢對象,又稱為OBC(Object By Criteria)
@Test
public void demo() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
/**
* Criteria
* 創(chuàng)建Criteria對象
* 調(diào)用方法
*/
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
for (User user : list) {
System.out.println(user);
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
SQLQuery用來接收SQL語句,需要我們手動封裝數(shù)據(jù)
@Test
public void demo03() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
/**
* 對象
* 調(diào)用方法
*/
String sql = "select * from `tb_user`";
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.addEntity(User.class);
List<User> list = sqlQuery.list();
// List<Object[]> list = sqlQuery.list();
// for (Object[] user : list) {
// System.out.println(Arrays.toString(user));
// }
for (User user : list) {
System.out.println(user);
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。