Hibernate教程如何配置二级缓存解决查询性能问题

admin Hibernate教程 8


做 Hibernate 开发的朋友,是不是常遇到这种情况:项目里查询操作特别多,数据库天天 “累得喘气”,明明没多少数据,查询却慢得像蜗牛爬?其实啊,很多时候不是数据库不行,而是你没用好 Hibernate 的二级缓存。这玩意儿就像个 “数据中转站”,能把常用数据存在内存里,不用每次都去麻烦数据库。今天兔子哥就手把手教你配置二级缓存,亲测能让查询性能提个好几档,都是实战里攒的干货!

一、先搞懂:二级缓存到底是个啥?


估计有新手会问:“Hibernate 不是有缓存吗?为啥还要单独搞二级缓存?” 这你就不知道了,Hibernate 有两种缓存,脾气可不一样:
缓存类型作用范围生命周期适用场景
一级缓存单个 Session 内有效随 Session 创建 / 关闭单次请求内的重复查询
二级缓存所有 Session 共享随 SessionFactory 存在多请求共享的高频查询数据

说白了,一级缓存只能管一个 Session,多个用户访问时就没用了;而二级缓存是全局共享的,谁查过的数据大家都能用。就像上次我们做商品列表页,没开二级缓存时,每个用户刷新一次就查一次数据库,并发高了数据库直接卡壳;开了二级缓存后,第一个用户查完数据存起来,后面的用户直接读缓存,数据库压力一下就降了 60%!

二、为啥要配二级缓存?这些场景非它不可


可能有朋友觉得 “配置缓存多麻烦,直接查数据库不行吗?” 但遇到这些场景,你就知道二级缓存多香了:
  1. 高频查询静态数据:像商品分类、地区字典、系统参数这些数据,十天半个月才更一次,却天天被查,放二级缓存里再合适不过
  2. 多用户共享数据:比如热门商品详情,很多用户同时看,缓存起来能少走 N 次数据库
  3. 查询比更新频繁的表:有些表查得多、改得少,比如用户等级表,缓存后能明显提速

不过话说回来,二级缓存也不是万能的。要是你的表数据天天变,比如订单表、库存表,就别折腾缓存了,不然刚存进去就过期,反而浪费资源。


三、实战配置:三步搞定二级缓存


配置二级缓存看着复杂,其实按步骤来特简单。兔子哥以最常用的 EhCache 为例,详细的设置方法,一起看看吧!

1. 先装 “插件”:加依赖


想用车得先加油,配置二级缓存第一步得把缓存框架的依赖加上。Maven 项目直接在 pom.xml 里加这段:
xml
<dependency><groupId>org.hibernate.ormgroupId><artifactId>hibernate-coreartifactId><version>6.4.4.Finalversion>dependency><dependency><groupId>org.hibernate.ormgroupId><artifactId>hibernate-ehcacheartifactId><version>6.4.4.Finalversion>dependency>

注意版本要和你的 Hibernate 版本对应,不然容易出兼容问题,我之前就因为版本不对踩过坑,调了半天才发现是依赖版本不匹配。

2. 开开关:配置 Hibernate 参数


依赖加好了,得告诉 Hibernate “我要开二级缓存啦”。在 application.yml(或 hibernate.cfg.xml)里加这些配置:
yaml
spring:jpa:properties:hibernate:cache:use_second_level_cache: true  # 开启二级缓存region.factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory  # 指定用EhCacheuse_query_cache: true  # 开启查询缓存(可选)

这里的use_query_cache是管查询缓存的,如果你想缓存 HQL/JPQL 查询结果,就把它设为 true,不过得配合代码里的query.setCacheable(true)才管用。

3. 选数据:给实体类加缓存注解


最后一步,告诉 Hibernate 哪些数据要进缓存。在实体类上用@Cache注解标记,比如商品分类表:
java
@Entity@Table(name = "t_category")@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)  # 只读缓存,适合静态数据public class Category {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;private String name;  # 分类名称private String description;  # 分类描述// getter、setter别忘了写}

这里的usage参数很关键,不同场景选不同策略:
  • READ_ONLY:适合只读数据,比如字典表,性能最好
  • READ_WRITE:适合读多写少的数据,比如商品信息
  • NONSTRICT_READ_WRITE:适合偶尔更新的数据,性能比 READ_WRITE 好但一致性稍弱

我一般给静态表用 READ_ONLY,给商品表用 READ_WRITE,亲测这样搭配性能最稳。


四、自问自答:这些坑你肯定遇到过


问:配置完二级缓存,为啥查询还是走数据库?
答:先检查实体类有没有加@Cache注解,再看缓存策略是不是选错了。还有啊,如果你查的是单条数据,得用session.get()session.load(),用session.createQuery()的话要记得加setCacheable(true),不然 Hibernate 不认缓存。
问:缓存的数据更新了,怎么让缓存同步?
答:用 READ_WRITE 或 NONSTRICT_READ_WRITE 策略时,Hibernate 会自动同步缓存。但如果是手动改数据库(比如用原生 SQL),缓存就不会更新,这时候得手动清缓存:sessionFactory.getCache().evict(Category.class),把整个分类表的缓存清掉。
问:二级缓存会不会占太多内存?
答:会!所以别啥数据都往里塞。可以在 EhCache 的配置文件 ehcache.xml 里设置缓存大小和过期时间,比如:
xml
<cache name="com.example.entity.Category"  # 对应实体类全路径maxEntriesLocalHeap="1000"  # 最多存1000条timeToLiveSeconds="3600"/>  # 1小时过期

这样就能防止缓存无限膨胀了。


五、兔子哥的实战心得


配置二级缓存这事儿,说难不难,说简单也得讲究技巧。我踩了不少坑才总结出这些经验:
  1. 从静态数据开始试:别一上来就给所有表开缓存,先从分类、字典这些静态表开始,看看效果再扩大范围
  2. 别迷信 “全量缓存”:频繁更新的表千万别开缓存,上次有个同事给订单表开了缓存,结果订单状态更新后缓存没同步,用户看到的还是旧状态,差点出大问题
  3. 一定要测试性能:配置完用 JMeter 压测下,对比缓存前后的查询时间和数据库压力,不是开了缓存就一定快,配置不对反而会变慢

其实二级缓存就像给数据库 “减负” 的帮手,用好了能省大事儿。刚开始可能会觉得配置麻烦,但多练两个例子就熟了。建议大家先在测试环境搭个小项目试试,感受下缓存带来的性能提升,你会回来感谢我的!

标签: org.hibernate.orm SessionFactory

发布评论 0条评论)

  • Refresh code

还木有评论哦,快来抢沙发吧~