实体开启@Cacheable二级缓存时,EntityManager.getReference()和find()有区别吗?
问题解答
二者行为不完全一致,即便实体B已经开启二级缓存,两者的核心逻辑和开销依然存在明显差异:
- 核心逻辑差异
getReference()本质是返回实体的懒加载代理对象,调用阶段不会触发任何查询动作:既不会查数据库,也不会主动查询二级缓存,只会基于你传入的主键生成代理实例。只有当你后续访问该代理的非主键字段时,才会依次查询一级缓存、二级缓存,缓存不命中才发起SQL查询。find()调用后会立刻触发全量查询逻辑:优先查当前持久上下文的一级缓存,再查二级缓存,都不命中才发起SQL查询数据库,返回的是已经完成初始化的实体对象,不是代理类型。
- 适配你的场景的选择建议
你当前的需求是更新关联了B的实体A,仅需要B的主键作为外键关联值,不需要访问B的其他字段,这种场景下哪怕B开了二级缓存,依然优先用getReference():- 不会触发任何查询(包括缓存查询),完全没有额外开销
- 避免了
find()方法带来的二级缓存查找、大实体反序列化的冗余开销
- 容易踩坑的特殊情况
如果你调用getReference()之后主动访问了B的非主键字段,此时才会触发二级缓存查询逻辑,返回的字段值和find()结果一致,但返回的对象本质还是代理类型,做instanceof之类的类型判断时要注意二者的差异。
内容的提问来源于stack exchange,提问作者Rey Libutan
相关产品推荐
相关产品推荐

