摘要:對象狀態(tài)中對象的狀態(tài)臨時瞬時狀態(tài)持久化狀態(tài)游離狀態(tài)學(xué)習(xí)的對象狀態(tài)是為了更清晰地知道的設(shè)計思想,以及是一級緩存的基礎(chǔ)當(dāng)然啦,也就一點點知識臨時瞬時狀態(tài)當(dāng)我們直接出來的對象就是臨時瞬時狀態(tài)的該對象還沒有被持久化沒有保存在數(shù)據(jù)庫中不受的管理持久化
對象狀態(tài)
Hibernate中對象的狀態(tài):
臨時/瞬時狀態(tài)
持久化狀態(tài)
游離狀態(tài)
學(xué)習(xí)Hibernate的對象狀態(tài)是為了更清晰地知道Hibernate的設(shè)計思想,以及是一級緩存的基礎(chǔ)...當(dāng)然啦,也就一點點知識
臨時/瞬時狀態(tài)當(dāng)我們直接new出來的對象就是臨時/瞬時狀態(tài)的..
該對象還沒有被持久化【沒有保存在數(shù)據(jù)庫中】
不受Session的管理
持久化狀態(tài)當(dāng)保存在數(shù)據(jù)庫中的對象就是持久化狀態(tài)了
當(dāng)調(diào)用session的save/saveOrUpdate/get/load/list等方法的時候,對象就是持久化狀態(tài)
在數(shù)據(jù)庫有對應(yīng)的數(shù)據(jù)
受Session的管理
當(dāng)對對象屬性進行更改的時候,會反映到數(shù)據(jù)庫中!
我們來測試一下:當(dāng)對對象屬性進行更改的時候,會反映到數(shù)據(jù)庫中!
session.save(idCard); idCard.setIdCardName("我是測試持久化對象");游離狀態(tài)
當(dāng)Session關(guān)閉了以后,持久化的對象就變成了游離狀態(tài)了...
不處于session的管理
數(shù)據(jù)庫中有對應(yīng)的記錄
一級緩存Hibernate有一級緩存和二級緩存之分,這里主要講解一級緩存
什么是一級緩存?Hibenate中一級緩存,也叫做session的緩存,它可以在session范圍內(nèi)減少數(shù)據(jù)庫的訪問次數(shù)! 只在session范圍有效! Session關(guān)閉,一級緩存失效!
只要是持久化對象狀態(tài)的,都受Session管理,也就是說,都會在Session緩存中!
Session的緩存由hibernate維護,用戶不能操作緩存內(nèi)容; 如果想操作緩存內(nèi)容,必須通過hibernate提供的evit/clear方法操作。
為什么要是使用緩存?減少對數(shù)據(jù)庫的訪問次數(shù)!從而提升hibernate的執(zhí)行效率!
測試我們來看一下Hibernate是怎么減少對數(shù)據(jù)庫訪問的次數(shù)的。
現(xiàn)在我的User表有這么一條記錄:
//把數(shù)據(jù)放進cache User user = (User) session.get(User.class, 1); //發(fā)現(xiàn)要修改的字段和cache一樣,不執(zhí)行 user.setUserName("你好2");
取數(shù)據(jù)也是一樣的
User user = null; user = (User) session.get(User.class, 1); user = (User) session.get(User.class, 1);緩存相關(guān)的方法
和緩存有關(guān)常用的方法有三個:
session.flush(); 讓一級緩存與數(shù)據(jù)庫同步
session.evict(arg0); 清空一級緩存中指定的對象
session.clear(); 清空一級緩存中緩存的所有對象
clear
User user = null; user = (User) session.get(User.class, 1); //清除緩存,那么下面獲取的時候,就不能從緩存里面拿了 session.clear(); user = (User) session.get(User.class, 1);
flush
在有緩存的情況下,修改同一條記錄的數(shù)據(jù),以最后的為準...因此只有一條update
User user = null; user = (User) session.get(User.class, 1); user.setUserName("我是第一"); user = (User) session.get(User.class, 1); user.setUserName("我是第二");
我讓強制讓它和數(shù)據(jù)庫同步的話,就有兩條update了
User user = null; user = (User) session.get(User.class, 1); user.setUserName("我是第一"); session.flush(); user = (User) session.get(User.class, 1); user.setUserName("我是第二");
一般地,我們在批處理的時候會用,因為緩存也是有大小的,如果1000條數(shù)據(jù)插入進去都要緩存,那么Hibernate可能就崩了...
每隔一定記錄數(shù),先與數(shù)據(jù)庫同步 flush()
再清空緩存 clear()
值得注意的是:不同的Session是不會共享緩存的!
Iterator與list我們使用HQL查詢?nèi)繑?shù)據(jù)的時候,可以使用list()得到所有的數(shù)據(jù),也可以使用iterator()得到一個迭代器,再遍歷迭代器...那它們有什么區(qū)別呢?
。。。。當(dāng)時看視頻的時候說是下圖:
但是我在測試的時候:List也可以獲取緩存的數(shù)據(jù)
當(dāng)然啦,Iterator也是可以獲取緩存的數(shù)據(jù)
因此,在獲取數(shù)據(jù)的時候還是使用list()方便!
懶加載懶加載就是當(dāng)使用數(shù)據(jù)的時候才去獲取數(shù)據(jù)、執(zhí)行對應(yīng)的SQL語句...當(dāng)還沒用到數(shù)據(jù)的時候,就不加載對應(yīng)的數(shù)據(jù)!
主要目的就是為了提高Hibernate的性能,提高執(zhí)行效率!
get: 及時加載,只要調(diào)用get方法立刻向數(shù)據(jù)庫查詢
load:默認使用懶加載,當(dāng)用到數(shù)據(jù)的時候才向數(shù)據(jù)庫查詢。
懶加載再次體驗User user = (User) session.load(User.class, 1); System.out.println("________"); System.out.println(user);
我們可以在對應(yīng)的配置文件用通常lazy屬性來設(shè)置
關(guān)閉懶加載:
lazy有三個屬性:
true 使用懶加載
false 關(guān)閉懶加載
extra (在集合數(shù)據(jù)懶加載時候提升效率)【只有在set、list等集合標簽中使用】
在真正使用數(shù)據(jù)的時候才向數(shù)據(jù)庫發(fā)送查詢的sql;
如果調(diào)用集合的size()/isEmpty()方法,只是統(tǒng)計,不真正查詢數(shù)據(jù)!
懶加載異常當(dāng)Session關(guān)閉后,就不能使用懶加載了,否則會報出異常
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
報出了這個異常,我們有4種方法解決:
方式1: 先使用一下數(shù)據(jù)
dept.getDeptName();
方式2:強迫代理對象初始化
Hibernate.initialize(dept);
方式3:關(guān)閉懶加載
設(shè)置lazy=false;
方式4: 在使用數(shù)據(jù)之后,再關(guān)閉session!
Hibernate二級緩存前面我們已經(jīng)講解過了一級緩存,一級緩存也就是Session緩存,只在Session的范圍內(nèi)有效...作用時間就在Session的作用域中,范圍比較小
Hibernate為我們提供了二級緩存功能:二級緩存是基于應(yīng)用程序的緩存,所有的Session都可以使用
Hibernate提供的二級緩存有默認的實現(xiàn),且是一種可插配的緩存框架!如果用戶想用二級緩存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影響代碼。
如果用戶覺得hibernate提供的框架框架不好用,自己可以換其他的緩存框架或自己實現(xiàn)緩存框架都可以。
Hibernate二級緩存:存儲的是常用的類
配置二級緩存既然二級緩存是Hibernate自帶的,那么我們可以在hibernate.properties文件中找到對應(yīng)的信息..
hibernate.cache.use_second_level_cache false【二級緩存默認不開啟,需要手動開啟】
hibernate.cache.use_query_cache true 【開啟查詢緩存】
choose a cache implementation 【二級緩存框架的實現(xiàn)】
hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider 默認實現(xiàn)
hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
通過配置文件我們可以發(fā)現(xiàn),二級緩存默認是不開啟的,需要我們手動開啟,以下步驟:
1)開啟二級緩存
2)指定緩存框架
3)指定哪些類加入二級緩存
開啟二級緩存在hibernate.cfg.xml文件中開啟二級緩存
指定緩存框架true
指定Hibernate自帶的二級緩存框架就好了
指定哪些類加入二級緩存org.hibernate.cache.HashtableCacheProvider
測試:
我們知道一級緩存是Session的緩存,那么我們在測試二級緩存的時候使用兩個Session來測試就好了。如果第二個Session拿到的是緩存數(shù)據(jù),那么就證明二級緩存是有用的。
package zhongfucheng.aa; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.classic.Session; public class App5 { public static void main(String[] args) { //獲取加載配置管理類 Configuration configuration = new Configuration(); //加載類對應(yīng)的映射文件! configuration.configure().addClass(Animal.class); //創(chuàng)建Session工廠對象 SessionFactory factory = configuration.buildSessionFactory(); //得到Session對象 Session session1 = factory.openSession(); //使用Hibernate操作數(shù)據(jù)庫,都要開啟事務(wù),得到事務(wù)對象 Transaction transaction = session1.getTransaction(); //開啟事務(wù) transaction.begin(); Monkey monkey = (Monkey) session1.get(Monkey.class,"40283f815be67f42015be67f43240001" ); System.out.println(monkey.getName()); System.out.println("-----------------------"); Session session2 = factory.openSession(); Transaction transaction2 = session2.getTransaction(); transaction2.begin(); Monkey monkey2 = (Monkey) session1.get(Monkey.class, "40283f815be67f42015be67f43240001"); System.out.println(monkey2.getName()); //提交事務(wù) transaction.commit(); transaction2.commit(); //關(guān)閉Session session1.close(); session2.close(); } }
得到的是緩存數(shù)據(jù)!
緩存策略我們在把Animal類放進二級緩存的時候,用法為只讀
也就是說,只能讀取,不能寫入,我們來看看寫入會怎么樣:
monkey2.setName("小猴子");
拋出了異常....
usage的屬性有4種:
如果我們在數(shù)據(jù)庫查詢的數(shù)據(jù)是集合...Hibernate默認是沒有為集合數(shù)據(jù)設(shè)置二級緩存的...因此還是需要去讀寫數(shù)據(jù)庫的信息
接下來,我們就看看把集合設(shè)置為二級緩存是什么做的:
在hibernate.cgf.xml中配置對象中的集合為二級緩存
測試代碼:
public void testCache() { Session session1 = sf.openSession(); session1.beginTransaction(); // a. 查詢一次 Dept dept = (Dept) session1.get(Dept.class, 10); dept.getEmps().size();// 集合 session1.getTransaction().commit(); session1.close(); System.out.println("------"); // 第二個session Session session2 = sf.openSession(); session2.beginTransaction(); // a. 查詢一次 dept = (Dept) session2.get(Dept.class, 10); // 二級緩存配置好; 這里不查詢數(shù)據(jù)庫 dept.getEmps().size(); session2.getTransaction().commit(); session2.close(); }查詢緩存
list()和iterator()會把數(shù)據(jù)放在一級緩存,但一級緩存只在Session的作用域中有效...如果想要跨Session來使用,就要設(shè)置查詢緩存
我們在配置文件中還看到了查詢緩存這么一條配置..
#hibernate.cache.use_query_cache true 【開啟查詢緩存】
也就是說,默認的查詢數(shù)據(jù)是不放在二級緩存中的,如果我們想要把查詢出來的數(shù)據(jù)放到二級緩存,就需要在配置文件中開啟
true
在使用程序查詢的時候,也要調(diào)用setCacheable()方法,設(shè)置為查詢緩存。
@Test public void listCache() { Session session1 = sf.openSession(); session1.beginTransaction(); // HQL查詢 【setCacheable 指定從二級緩存找,或者是放入二級緩存】 Query q = session1.createQuery("from Dept").setCacheable(true); System.out.println(q.list()); session1.getTransaction().commit(); session1.close(); Session session2 = sf.openSession(); session2.beginTransaction(); q = session2.createQuery("from Dept").setCacheable(true); System.out.println(q.list()); // 不查詢數(shù)據(jù)庫: 需要開啟查詢緩存 session2.getTransaction().commit(); session2.close(); }
如果文章有錯的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號:Java3y
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68715.html
摘要:要是使用到日歷的話,我們想到使用這個日歷類上面僅僅是我個人總結(jié)的要點,如果有錯誤的地方還請大家給我指正。 納稅服務(wù)系統(tǒng)總結(jié) 納稅服務(wù)系統(tǒng)是我第一個做得比較大的項目(不同于javaWeb小項目),該項目系統(tǒng)來源于傳智Java32期,十天的視頻課程(想要視頻的同學(xué)關(guān)注我的公眾號就可以直接獲取了) 我跟著練習(xí)一步一步完成需求,才發(fā)覺原來Java是這樣用來做網(wǎng)站的,Java有那么多的類庫,頁面...
摘要:前言由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號:Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...
摘要:屬性屬性表示控制權(quán)是否轉(zhuǎn)移控制權(quán)已轉(zhuǎn)移當(dāng)前一方?jīng)]有控制權(quán)控制權(quán)沒有轉(zhuǎn)移當(dāng)前一方有控制權(quán)屬性,是在維護關(guān)聯(lián)關(guān)系的時候起作用的。表的外鍵并沒有數(shù)據(jù)結(jié)論如果設(shè)置控制反轉(zhuǎn)即然后通過部門方維護關(guān)聯(lián)關(guān)系。 Inverse屬性 Inverse屬性:表示控制權(quán)是否轉(zhuǎn)移.. true:控制權(quán)已轉(zhuǎn)移【當(dāng)前一方?jīng)]有控制權(quán)】 false:控制權(quán)沒有轉(zhuǎn)移【當(dāng)前一方有控制權(quán)】 Inverse屬性,是在維護關(guān)聯(lián)...
摘要:一級緩存值得注意的地方默認就是支持一級緩存的,并不需要我們配置和整合后進行代理開發(fā),不支持一級緩存,和整合,按照的模板去生成代理對象,模板中在最后統(tǒng)一關(guān)閉。總結(jié)的一級緩存是級別的。 前言 本文主要講解Mybatis的以下知識點: Mybatis緩存 一級緩存 二級緩存 與Ehcache整合 Mapper代理 使用Mapper代理就不用寫實現(xiàn)類了 逆向工程 自動生成代碼 ...
摘要:前言前面的我們使用的是一個表的操作,但我們實際的開發(fā)中不可能只使用一個表的因此,本博文主要講解關(guān)聯(lián)映射集合映射需求分析當(dāng)用戶購買商品,用戶可能有多個地址。數(shù)據(jù)庫表我們一般如下圖一樣設(shè)計數(shù)據(jù)庫表,一般我們不會在表設(shè)計多個列來保存地址的。 前言 前面的我們使用的是一個表的操作,但我們實際的開發(fā)中不可能只使用一個表的...因此,本博文主要講解關(guān)聯(lián)映射 集合映射 需求分析:當(dāng)用戶購買商品,用戶...
閱讀 1644·2021-10-25 09:46
閱讀 3239·2021-10-08 10:04
閱讀 2386·2021-09-06 15:00
閱讀 2786·2021-08-19 10:57
閱讀 2093·2019-08-30 11:03
閱讀 993·2019-08-30 11:00
閱讀 2393·2019-08-26 17:10
閱讀 3562·2019-08-26 13:36