摘要:通過查詢實例調用上面的方法這里就算方法體里面執行三個查詢操作,也只會執行一條查詢,因為使用的同一個對象,這就有使用到的一級緩存。方法會使用二級緩存,而方法在一級緩存沒有找到的情況下會直接查詢數據庫,不會去二級緩存中查找。
一、什么是緩存
緩存是內存中少部分數據的復制品,所以CPU到緩存中尋找數據時,也會出現找不到的情況(因為這些數據沒有從內存復制到緩存中去),這時CPU還是會到內存中去找數據,這樣系統的速率就慢下來了,不過CPU會把這些數據復制到緩存中去,以便下一次不要再到內存中去取。
二、Hibernate的一級緩存
(1)使用
Hibernate的一級緩存是默認開啟的,當獲取到一個Session對象,并執行save、update、saveOrUpdate、get方法時就會用到Hibernate一級緩存,當然也可以調用清除的放方法,Session為清除緩存提供了clear(清除所有的一級緩存)、evict(清除實例對象緩存)、refresh(重新查詢數據并刷新緩存)。
例子:
//泛型查詢實例 public E find(S s) { //使用Spring 獲取一個Session對象 Session session = getSession(); //執行查詢操作 E bean = (E)session.get(entityClass, (Serializable) s); //清除實例對象緩存 session.evict(bean); //返回查詢的對象 return bean; }
(2)狀態
Hibernate緩存狀態分為瞬時狀態、持久狀態、脫管狀態。
瞬時狀態: 創建一個POJO,還未將對象數據保存到數據庫時,Session中也沒有當前POJO實例。
例子:
//創建一個POJO實例 Account account = new Account(); //給實例添加數據 account.setPhone("12345678931"); //這時實例并沒有保存
持久狀態: POJO對象被添加到Session緩存中,數據庫也要有對應的數據。
例子:
public Integer saveStatus(Account entity) { //獲取Session對象 Session session = getSession(); //執行保存方法 Integer id = (Integer)session.save(entity); //修改被持久化的POJO對象 entity.setState(4); //返回對象ID return id; }
在上面的例子中,當保存事務還未提交,這時數據已經被持久化。這里會執行兩條SQL,一條添加SQL,一條修改SQL(并沒有調用修改方法為什么會執行修改SQL呢?因為Hibernate被持久化的POJO對象在被重新賦值時會觸發更新操作。)
脫管狀態: 在緩存中已經被持久化的POJO對象,接著POJO對象執行了evict方法,這時POJO對象會從緩存中托管,但數據庫中是有對應的數據。
例子:
public Integer saveStatus(Account entity) { //獲取Session對象 Session session = getSession(); //執行保存方法 Integer id = (Integer)session.save(entity); //脫管當前POJO對象 session.evict(entity); //修改被持久化的POJO對象 entity.setState(4); //返回對象ID return id; }
調用evict方法將POJO對象傳入,清除實例的持久化,修改POJO實例將不會在觸發更新操作。
(3)緩存綁定
Hibernate的一級緩存是綁定Session的,當獲取到一個Session對象,在執行Sessinon里面的方法都能使用Hibernate默認提供的一級緩存,執行完成Session對象消亡即緩存數據也跟著消亡(一級緩存的數據是放在棧中)。
例子:
//通過id查詢POJO實例 public E find(S s) { Session session = getSession(); E bean = (E)session.get(entityClass, (Serializable) s); return bean; } //調用三次上面的方法 accountService.find(1); accountService.find(1); accountService.find(1);
這里會執行三條查詢SQL,這是因為里面獲取的Session對象是線程安全的,彼此并沒有任何關聯(這也是為什么Spring不能用到Hibernate的一級緩存,其實不是Spring的問題)。
//通過id查詢POJO實例 public E find(S s) { Session session = getSession(); E bean = (E)session.get(entityClass, (Serializable) s); E bean1 = (E)session.get(entityClass, (Serializable) s); E bean2 = (E)session.get(entityClass, (Serializable) s); return bean; } //調用上面的方法 accountService.find(1);
這里就算方法體里面執行三個查詢操作,也只會執行一條查詢SQL,因為使用的同一個Session對象,這就有使用到Hibernate的一級緩存。
二、Hibernate的二級緩存
(1)使用
Hibernate的二級緩存是默認關閉的(二級緩存的數據是放在堆中),如果需要開啟二級緩存則需要額外的配置。
(2)配置
第一步:POJO對象設置
@Entity//POJO注解 @Table(name = "account")//對應的數據庫表名稱 @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)//二級緩存配置,讀寫模式 public class Account { ... }
第二步:配置Hibernate session工廠
update org.hibernate.dialect.MySQLDialect true true true true org.hibernate.cache.ehcache.EhCacheRegionFactory classpath:applicationContext-ehcache.xml
com.test.entity
第三步:創建二級緩存配置文件
//maxElementsInMemory--緩存對象的最大數目 //eternal--對象是否永不過期,設置為true,過期時間則無效 //timeToldleSeconds--對象空閑多長時間未被使用就失效 //timeToLiveSeconds--對象被緩存的時間 //overflowToDisk--內存溢出時是否刷盤,如果為true則需要配置一個刷盤路徑 //diskExpiryThreadIntervalSeconds--磁盤失效線程運行時間間隔
三、選擇正確的方法
(1) Hibernatne查詢分為兩類:一類是得到單個對象,另一類是得到結果集。
單個對象:
get()方法和load()方法的區別在于對二級緩存的使用上。load()方法會使用二級緩存,而get()方法在一級緩存沒有找到的情況下會直接查詢數據庫,不會去二級緩存中查找。在使用中,對使用了二級緩存的對象進行查詢時最好使用load()方法,以充分利用二級緩存來提高檢索的效率。
結果集對象:
list方法介紹
list()方法在執行時,是直接運行查詢結果所需要的查詢語句,而iterator()方法則是先執行得到對象ID的查詢,然后再根據每個ID值去取得所要查詢的對象。因此,對于list()方式的查詢通常只會執行一個SQL語句,而對于iterator()方法的查詢則可能需要執行N+1條SQL語句(N為結果集中的記錄數)。
list()方法只能使用二級緩存中的查詢緩存,而無法使用二級緩存對單個對象的緩存(但是會把查詢出的對象放入二級緩存中)。所以,除非重復執行相同的查詢操作,否則無法利用緩存的機制來提高查詢的效率。
list()方法會一次獲得所有的結果集對象,而且它會依據查詢的結果初始化所有的結果集對象。這在結果集非常大的時候必然會占據非常多的內存,甚至會造成內存溢出情況的發生。
iterator方法介紹
iterator()方法只是可能執行N+1條數據,具體執行SQL語句的數量取決于緩存的情況以及對結果集的訪問情況。
iterator()方法則可以充分利用二級緩存,在根據ID檢索對象的時候會首先到緩存中查找,只有在找不到的情況下才會執行相應的查詢語句。所以,緩存中對象的存在與否會影響到SQL語句的執行數量。
iterator()方法在執行時不會一次初始化所有的對象,而是根據對結果集的訪問情況來初始化對象。因此在訪問中可以控制緩存中對象的數量,以避免占用過多緩存,導致內存溢出情況的發生。使用iterator()方法的另外一個好處是,如果只需要結果集中的部分記錄,那么沒有被用到的結果對象根本不會被初始化。所以,對結果集的訪問情況也是調用iterator()方法時執行數據庫SQL語句多少的一個因素。
部分信息來自網絡,歡迎大家指出錯誤。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/62023.html
摘要:通過查詢實例調用上面的方法這里就算方法體里面執行三個查詢操作,也只會執行一條查詢,因為使用的同一個對象,這就有使用到的一級緩存。方法會使用二級緩存,而方法在一級緩存沒有找到的情況下會直接查詢數據庫,不會去二級緩存中查找。 一、什么是緩存 緩存是內存中少部分數據的復制品,所以CPU到緩存中尋找數據時,也會出現找不到的情況(因為這些數據沒有從內存復制到緩存中去),這時CPU還是會到內存中去...
摘要:中怎樣實現類之間的關系如一對多多對多的關系中怎樣實現類之間的關系如一對多多對多的關系它們通過配置文件中的來實現類之間的關聯關系的。 Hibernate常見面試題 Hibernate工作原理及為什么要用? Hibernate工作原理及為什么要用? 讀取并解析配置文件 讀取并解析映射信息,創建SessionFactory 打開Sesssion 創建事務Transation 持久化操作 提...
摘要:一級緩存又叫的緩存,是事物范圍的緩存,默認開啟二級緩存又叫的緩存,默認關閉。二級緩存存放數據一般是不經常修改的數據,不會被并發訪問的數據,常量數據訪問數據順序是一級緩存二級緩存數據庫。 Hibernate與mybatis比較 1、先說底層: a)Jdbc:全稱java數據庫連接,是java語言用來規范客戶端如何訪問數據庫的程序接口。 b) 一般步驟: i.加載驅動程序 ...
摘要:使用反射機制,而不是字節碼增強程序來實現透明性。工具類初始化失敗為空,請檢查配置文件瞬時對象與持久化對象測試代碼當前在數據庫中沒有記錄進行關聯,所以此時是瞬時對象。將持久化當前在數據庫有唯一一條記錄對應,所以此時是持久化對象。 showImg(https://segmentfault.com/img/bVbo4at?w=2313&h=642); 一、什么是Hibernate? Hibe...
摘要:面試總結最近兩周面試了幾家公司高級工程師的職位,主要有宜信網信金融阿里高德口袋購物。目前有部分公司已經面試通過,兩家在等消息。今天趁熱把常見面試內容總結一下。可以用來完成統一命名服務狀態同步服務集群管理分布式應用配置項等管理工作。 面試總結 最近兩周面試了幾家公司Java高級工程師的職位,主要有宜信、網信金融、阿里高德、口袋購物。目前有部分公司已經面試通過,兩家在等消息。今天趁熱把常見...
閱讀 2101·2021-11-18 10:02
閱讀 2850·2021-09-04 16:41
閱讀 1142·2019-08-30 15:55
閱讀 1405·2019-08-29 17:27
閱讀 1070·2019-08-29 17:12
閱讀 2535·2019-08-29 15:38
閱讀 2855·2019-08-29 13:02
閱讀 2831·2019-08-29 12:29