Hibernate6-Session緩存

在說Session緩存之前我們先修改一下我們的項(xiàng)目,在項(xiàng)目中添加兩個(gè)方法

@Before
public void setUp() throws Exception {

}

@After
public void tearDown() throws Exception {

}

我的這兩個(gè)方法是我使用ide生成的,我們使用單元測試測試某個(gè)方法的時(shí)候,junit會(huì)先幫我執(zhí) setup ()方法,當(dāng)單元測試結(jié)束后junit會(huì)為我們執(zhí)行tearDown()方法。當(dāng)然方法名無所為,只要符合規(guī)定就可以隨便寫,主要的是@Before與@After這兩個(gè)注解。我們將hibernateTest1()
方法中的代碼剪切出來最終改造成這個(gè)樣子

public class HibernateTest {
    private Session session = null;
    private Transaction transaction = null;

    @Before
    public void setUp() throws Exception {
        StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
        SessionFactory sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();

        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
    }

    @After
    public void tearDown() throws Exception {
        transaction.commit();
        session.close();
    }


    @Test
    public void hibernateTest1(){

    }
}

看明白了吧,在開始單元測試的時(shí)候幫我們獲取一個(gè)Session對象并且開啟一個(gè)事務(wù),結(jié)束單元測試的時(shí)候,幫我們提交事務(wù)和關(guān)閉Session。

獲取一條記錄

????還記得我們在數(shù)據(jù)庫中插入了一條 name字段值為張三的一條記錄吧?我們現(xiàn)在來從數(shù)據(jù)庫中取出來。哦,對了我忘了和大家說一下由于Mac電腦安裝oracle安裝比較麻煩,再者使用服務(wù)器還是有點(diǎn)不方便。以后我都會(huì)使用mysql社區(qū)版做演示。


Hibernate6-1.png

可以看出跟我們的預(yù)期效果是一樣,發(fā)送了一條sql語句來查詢數(shù)據(jù),我們在使用get方法獲取一遍數(shù)據(jù)


Hibernate6-2.png

????可以看出連續(xù)兩條打印結(jié)果,但是只發(fā)送了一條sql語句來做查詢。那么問題來了,為什么第一遍使用get方法獲取數(shù)據(jù)需要發(fā)送sql語句,而第二次使用get方法獲取數(shù)據(jù)則不需要發(fā)送sql語句了呢?
????這是因?yàn)?,你第一次使用get方法的時(shí)候session會(huì)將你的要查詢的數(shù)據(jù)拿出來返回給你之后,并且會(huì)在session緩存中保存一份,所以當(dāng)你在同一個(gè)session中查詢相同數(shù)據(jù)的時(shí)候,會(huì)先到自己的緩存中去找,如果有則返回給你,如果沒有就去二級緩存中找,如果在沒有數(shù)據(jù)彩繪發(fā)送sql語句從數(shù)據(jù)庫中查找。

操作session緩存

????flush:當(dāng)我們調(diào)用flush方法時(shí),會(huì)將我們的增刪改操作同步到數(shù)據(jù)庫中。
????reflesh:強(qiáng)制同步緩存中的一個(gè)對象,就是說我們獲取了數(shù)據(jù),當(dāng)我們過了一段時(shí)間要繼續(xù)使用此數(shù)據(jù)的時(shí)候,但是不確定別人是否修改了此數(shù)據(jù),所以使用此方法來重新獲取一遍。當(dāng)然我們也可以先使用evict 方法將對象從session緩存中移除,然后在使用????get 方法獲取。
????clear:清空緩存。
????evict:從session緩存中移除某個(gè)對象。
????commit和flush區(qū)別:flush執(zhí)行一系列sql語句,但不提交事務(wù);commit方法先調(diào)用flush方法,然后提交事務(wù)。

理論

????一級緩存生命周期很短與Session生命周期一致,所以一級緩存也叫Session緩存或事物級緩存。為什么也叫事務(wù)級緩存呢,是因?yàn)樵鰟h改方法需要事務(wù)來完成,每次執(zhí)行增刪改后都要commit,所以也叫事務(wù)級緩存。
????位于緩存中的對象處于持久化狀態(tài),它和表中的相關(guān)記錄對應(yīng),Session能夠在某些時(shí)間點(diǎn),按照緩存中持久話對象的屬性變化來同步數(shù)據(jù)庫中表的記錄,這一過程稱為清理緩存。也就是說當(dāng)我們使用get方法查詢出數(shù)據(jù)庫某條記錄的時(shí)候,這時(shí)對象就處于持久狀態(tài),例如:User user = session.get(User.class, 1);
我們從數(shù)據(jù)庫中查詢出主鍵為1的數(shù)據(jù),這個(gè)時(shí)候user對象就處于持久狀態(tài)。說白了就是通過session得到的對象都是持久狀態(tài)對象。
????當(dāng)我們修改了此對象的屬性值,在使用session的方法進(jìn)行提交和刷新緩存時(shí),就會(huì)將你修改過的對象屬性值同步到數(shù)據(jù)庫表中,在提交或刷新緩存時(shí)的過程稱為清理緩存。當(dāng)然清理緩存不只是提交和刷新緩存,還有別的方法。

一級緩存實(shí)現(xiàn)原理:

????session緩存是由它的實(shí)現(xiàn)類SessionImpl中定義的一些集合屬性構(gòu)成的,原理是保證有一個(gè)引用在關(guān)聯(lián)某個(gè)持久話對象,保持它的生命周期不會(huì)結(jié)束。 大家都知道java中有垃圾回收器也就是GC,如果我們長時(shí)間不使用某個(gè)對象,那么他會(huì)在一定時(shí)間內(nèi),被java的垃圾回收器從內(nèi)存中清理掉,所以hibernate為了防止通過session獲取的對象被清理掉,在session緩存中一直保持著此對象的引用,直到session被關(guān)閉。

一級緩存的作用

????減少數(shù)據(jù)庫訪問量,例如我們總是要獲取數(shù)據(jù),每次都要鏈接數(shù)據(jù)庫查詢,這樣大大降低了運(yùn)行效率,所以我們都會(huì)通過session緩存來獲取數(shù)據(jù)。

配圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容