Hibernate缓存机制

缓存定义:
缓存是在内存中专门分配的空间,用于存储原本应存储在硬盘上的数据,以便加快数据访问速度。所有查询操作都可能将数据存入缓存中,从而减少对硬盘存储器的频繁访问,提高系统性能。

一级缓存(Session 级别缓存):

  • 一级缓存是线程级别的缓存,与每个 Hibernate Session 相关联。

  • 查询时,除非使用 get 或 load 方法,否则不会优先从缓存中获取数据,但在对象实例化过程中会检查缓存是否存在匹配的对象。

  • update(user) 方法会更新缓存中的对象。

  • query.executeUpdate() 不会更新缓存。

  • load 方法流程:首先检查一级缓存 -> 检查二级缓存 -> 若均未命中,则访问数据库 -> 数据填充至一级缓存(可能也填充至二级缓存)并返回代理对象。

    整理了一份面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题

    需要全套面试笔记的【点击此处即可】即可免费获取

  • get 方法类似,若缓存中有匹配对象,则直接返回缓存中的数据。

  • 缓存特性:持久化对象会自动同步其变化到数据库中。

  • 快照:在一级缓存旁边维护着对象数据的备份,确保数据库和一级缓存数据的一致性。当一级缓存数据被修改且事务提交时,一级缓存会被刷新,并执行更新操作将缓存数据更新至数据库。

  • 更新与 saveOrUpdate 方法:

    • update 方法针对已具有持久化标识的对象执行更新操作。
    • saveOrUpdate 方法会根据对象是否有持久化标识决定执行更新或插入操作。
  • savepersist 与 merge 的区别:

    • save 方法:即使在调用前设置了 ID 值,也会遵循数据库的 ID 生成策略,而不是使用用户设置的 ID。
    • persist 方法:如果设置了 ID,会尝试查找数据库中对应 ID 的记录,不存在则插入,存在则抛出异常。
    • merge 方法:对于带有 ID 的对象视为游离态对象处理,如果在数据库中找到匹配的 ID,则执行更新操作;如果没找到,则执行插入;若未设置 ID,则视作瞬态对象。
  • flush 与 update 区别:

    • flush:手动强制刷新缓存,使其内容与数据库同步。
    • update:在事务提交时,会自动触发 flush 操作,将缓存中的更改同步至数据库。
  • lock 与 update 区别:

    • lock:将一个尚未更改过的托管对象变为持久化状态。
    • update:将一个已更改的托管对象转变为持久化状态。
  • clear 与 evict 区别:

    • clear:清空 Session 缓存中的所有数据。
    • evict:从 Session 缓存中移除指定的持久化对象。

二级缓存

二级缓存是进程级别的缓存,它的键(key)通常是对象的唯一标识符(如ID),值(value)则是对象本身。这种缓存位于SessionFactory级别,因此能够在不同Session之间共享数据,使得多个Session能够共用缓存内容。

SessionFactory缓存构成

SessionFactory缓存分为两个部分:

  1. 内置缓存

    • 这是一个只读的Map结构,用于存储Hibernate框架所需的配置信息、预定义的HQL语句等内部数据。
    • 内置缓存仅供Hibernate框架内部使用,外部无法直接操作,也不支持卸载。
  2. 外置缓存(二级缓存)

    • 使用另一个Map来存储用户自定义的、需要跨Session共享的数据。
    • 外置缓存默认情况下并未开启,Hibernate仅提供缓存规范和接口,具体的实现通常由第三方缓存提供者完成,例如EHCache、Redis等。
    • 当开启二级缓存后,它可以被不同的Session访问和共享,并且在不需要使用时可以卸载或重新配置。

缓存访问方法

  • loadget 以及 iterate 方法都会利用二级缓存来提升数据获取效率。其中,iterate 方法虽然底层也是使用 load,但它会在查询过程中发送SQL查询ID值,然后根据ID逐个加载对象。

  • 当查询使用 query.list() 方法时,如果查询缓存已启用,那么查询的结果将根据SQL语句作为键,ID作为值存储在缓存中。在后续相同的查询条件下,可以直接从缓存中获取ID,进而逐个加载对象。

二级缓存组成要素

  • 类级别缓存(Class Cache):存储对象自身的散列数据,即非集合属性的内容。

  • 集合级别缓存(Set Cache):用于存放关联对象的OID(对象标识符),主要针对对象集合属性。

  • 时间戳缓存:记录对象最后更新的时间戳信息,用于判断缓存是否过期或数据是否脏读。

  • 查询缓存(Query Cache):作为二级缓存的一部分,有时也称为三级缓存,它基于SQL查询结果进行缓存。查询缓存将查询语句及其结果进行绑定,当同一查询被执行时,可以从缓存中快速获取结果。

适用场景

二级缓存适用于那些访问频繁但改动较少的数据,允许一定程度的并发访问,并且数据总量相对有限的情况。

缓存内部结构图

image.png

二级缓存的使用方法

  • XML配置方式:通过在Hibernate的配置文件中添加特定的属性和配置来启用二级缓存。

  • 注解方式:在实体类上使用 @Cache 注解来声明使用二级缓存,可以选择缓存并发策略,如:

    • @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 表示可读写缓存。
    • @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) 表示只读缓存。

查询缓存的启用与使用

  • 开启查询缓存:在Hibernate配置文件中设置 <property name="cache.use_query_cache">true</property> 来开启查询缓存功能。

  • 在DAO层中使用查询缓存:在执行查询时,需要在Query对象上调用 query.setCacheable(true) 来启用查询缓存,这样查询结果将在符合条件的情况下从二级缓存中获取,而非直接从数据库查询。查询缓存默认是禁用的,需要显式开启才能使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值