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对象,当把全部实体类都开启二级缓存之后,(每次执行完操作都会自动将数据填充到一级缓存、二级缓存中),一级缓存倒不用担心,因为它每次用完之后会关闭,但是二级缓存则是一直存在的,长时间的缓存数据会将我们的内存撑爆的。那么问题来了,我们应该在什么情况下使用二级缓存呢?

二级缓存使用场景

  • 读取大于修改,数据经常被查询,而很少修改
    因为我们要保证数据库与缓存数据一致,所以每当用户修改数据之后,就需要将缓存与数据库同步,所以实质上还是会频繁操作数据库,此时使用缓存技术就没多大作用

  • 独享控制,数据库数据不能被第三方修改
    如果用户使用第三方工具修改了数据库信息,则会导致数据库与缓存中的数据不一致,这时如果没有及时的同步则是会出现很大的问题的。

  • 允许出现无效数据
    使用缓存技术,难免会出现数据精度丢失(数据库与缓存数据不一致)的情况。故,对数据精度要求高的系统是不能使用缓存技术的

  • 数据量不超过内存
    缓存技术是将数据缓存在内存中的,如果数据量超过了内存,那后果可想而知

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值