JPA緩存

JPA緩存(Hibernate實現)

一級緩存對象

在JPA中我們是通過EntityManager對象操作數據庫實現CRUD操作,在它身上裝着數據庫連接對象以及一級緩存對象。而我們的EntityManager對象又是使用Persistence對象讀取JPA配置文件persistence.xml獲取到持久化單元(persistence-unit),創建entityManagerFactory對象

entityManagerFactory = Persistence.createEntityManagerFactory("com.xer.jpa");

再通過entityManagerFactory創建而得

EntityManager entityManager = entityManagerFactory.createEntityManager();

當我們具體操作數據庫時,例如使用entityManager 對象的find方法(查詢一條數據)時,首先會在entityManager對象中去查詢是否存在一級緩存對象
如果存在:則直接使用,而不會發送SQL語句
如果不存在:則會發送SQL語句,操作數據庫進行查詢,數據庫會返回一個查詢結果,查詢出的數據,此時,會將這條數據填充到entityManager的一級緩存中

證明一級緩存存在

 @Test
    public void testQuery() {
        EntityManager entityManager = JPAUtil.getEntityManager();
        Student student = entityManager.find(Student.class, 1L);
        System.out.println(student);
        Student student1 = entityManager.find(Student.class, 1L);
        System.out.println(student1);
        entityManager.close();
    }

在這裏插入圖片描述

會發現我進行了兩次查詢操作,卻只執行了一條SQL,說明第二次並沒有向數據庫發送SQL而是直接使用了一級緩存中的數據(兩次查詢的數據條件一致)
我們將在一級緩存中找到對應數據稱爲一級緩存命中

一級緩存命中

條件:同一個entityManagerFactory,同一個entityManager,同一個OID

  1. OID:在執行完數據庫操作之後,將數據放入到Map中時(緩存對象基本上都是以map形式存在的),會爲其生成一個唯一的key:實體類全限定名#id
    在這裏插入圖片描述
    其中entityKey則被稱爲OID

二級緩存對象

二級緩存對象默認是未啓用的狀態,如果想要啓用二級緩存需要配置

  1. 導包
    需要導入相應的緩存包
    在這裏插入圖片描述
    由於我搭建的maven項目,所以在pom中配置即可,只需配置hibernate-ehcache
 <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>4.3.8.Final</version>
        </dependency>
  1. 配置persistence.xml
<persistence-unit name="cn.itsource.jpa" transaction-type="RESOURCE_LOCAL">
        <!--設置二級緩存掃描策略-->
        <!--
            ALL:所有的實體類都會被緩存
            NONE:所有實體類都不會被緩存
            ENABLE_SELECTIVE:標識了@Cacheable(true)註解的實體類將會被緩存
            DISABLE_SELECTIVE:將會緩存標識了@Cacheable(false)以外的實體類
            UNSPECIFIED:默認值
        -->
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
        <properties>

            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"></property>
            <property name="hibernate.connection.url" value="jdbc:mysql:///mydb"></property>
            <property name="hibernate.connection.username" value="xer"></property>
            <property name="hibernate.connection.password" value="123456"></property>

            <!--
                配置二級緩存
                二級緩存默認是未啓用的,所以需要配置啓用
            -->
            <!--啓用二級緩存-->
            <property name="hibernate.cache.use_second_level_cache" value="true"></property>
            <!--
                啓用查詢緩存
                即查詢操作時也使用緩存,但是一般是不會開啓的
            -->
            <property name="hibernate.cache.use_query_cache" value="true"></property>
            <!--
                支持二級緩存的工廠
                hibernate的配置文件中關於ehcache的工廠支持配置是錯誤的
                將internal改爲ehcache即可
            -->
            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"></property>
             </properties>
    </persistence-unit>
  1. 在需要被緩存的實體類上標註@Cacheable註解

這樣我們就算完成了二級緩存開啓及配置,接下來測試一下

@Test
    public void testQueryT() {
        EntityManager entityManager = JPAUtil.getEntityManager();
        Teacher t = entityManager.find(Teacher.class, 1L);
        System.out.println(t);
        Teacher t1 = entityManager.find(Teacher.class, 1L);//一級緩存命中
        System.out.println(t1);
        entityManager.close();

        EntityManager entityManager1 = JPAUtil.getEntityManager(); 
        Teacher t2 = entityManager1.find(Teacher.class, 1L); //二級緩存命中
        System.out.println(t2);
        Teacher t3 = entityManager1.find(Teacher.class, 1L);//一級緩存命中
        System.out.println(t3);
        entityManager1.close();
    }

在這裏插入圖片描述
可以看到同樣的發送了一條SQL語句
在這裏插入圖片描述

總結:
在實際開發中,如果頻繁的操作數據庫,這樣會對數據庫造成很大的負擔,使用了緩存技術,可以大大的減少訪問數據庫的次數,從而達到性能最優的效果。但是因爲在一個應用中,我們應該保證只有一個entityManagerFactory對象,當把全部實體類都開啓二級緩存之後,(每次執行完操作都會自動將數據填充到一級緩存、二級緩存中),一級緩存倒不用擔心,因爲它每次用完之後會關閉,但是二級緩存則是一直存在的,長時間的緩存數據會將我們的內存撐爆的。那麼問題來了,我們應該在什麼情況下使用二級緩存呢?

二級緩存使用場景

  • 讀取大於修改,數據經常被查詢,而很少修改
    因爲我們要保證數據庫與緩存數據一致,所以每當用戶修改數據之後,就需要將緩存與數據庫同步,所以實質上還是會頻繁操作數據庫,此時使用緩存技術就沒多大作用

  • 獨享控制,數據庫數據不能被第三方修改
    如果用戶使用第三方工具修改了數據庫信息,則會導致數據庫與緩存中的數據不一致,這時如果沒有及時的同步則是會出現很大的問題的。

  • 允許出現無效數據
    使用緩存技術,難免會出現數據精度丟失(數據庫與緩存數據不一致)的情況。故,對數據精度要求高的系統是不能使用緩存技術的

  • 數據量不超過內存
    緩存技術是將數據緩存在內存中的,如果數據量超過了內存,那後果可想而知

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章