JPA 二级缓存问题请教

2020-08-27 10:20:58 +08:00
 NULL2020

service 层两个查询方法:

    @Cacheable(value = "space", key = "#id", unless = "#result==null")
    public Space searchOne(long id) {
        return repository.findById(id).orElse(null);
    }

    public Space searchOneWithUser(long id) {
        Space space = searchOne(id);
        space.setCreator(userService.searchOne(space.getUserId()));
        return space;
    }

为什么调用第二个方法不走缓存? 缓存有数据还是从数据库里查,缓存没有数据,查出来后也不写到缓存里面。

1861 次点击
所在节点    Java
11 条回复
CoderGeek
2020-08-27 10:30:01 +08:00
这个是基于 AOP 的动态代理实现,你内部引用不生效
1.放到外部的类调用
2.用 ApplicationContext.getBean 在调用 searchOne(id)
wysnylc
2020-08-27 10:38:52 +08:00
https://www.jianshu.com/p/6534945eb3b5
JDK Dynamic Proxy 无法拦截 this,Spring 默认使用 JDK Dynamic Proxy,所以 Spring AOP 无法代理 this 所以 Spring Cache 缓存注解无效.解决方案为注入当前类的 bean 进行使用(但是有可能造成循环调用)或者拆分逻辑到另一个 services
题外话:你这不是 JPA 二级缓存而是 Spring Cache 自定义缓存,二级缓存是基于表的缓存
NULL2020
2020-08-27 10:42:55 +08:00
@CoderGeek #1
@wysnylc #2

多谢多谢
ixx
2020-08-27 10:49:17 +08:00
多说一句,有一道关于事务的面试题就是你这么写的,把缓存注解换成事务注解 原理是一样的 ,调用第二个不走事务
NULL2020
2020-08-27 10:51:32 +08:00
@wysnylc #2 我的理解,二级缓存就是查询缓存,你说的 [基于表的缓存] 好像第一次听说,有没有技术文章可以分享一下?
NULL2020
2020-08-27 10:52:33 +08:00
@ixx #4 感谢,事务失效的几种原因之一 [自调用]
aragakiyuii
2020-08-27 10:52:42 +08:00
这个不是 orm 的二级缓存吧。。
cglib 代理完大概就这样(不准确

aragakiyuii
2020-08-27 10:57:04 +08:00
@aragakiyuii #7 extend -> extends
wysnylc
2020-08-27 12:17:04 +08:00
leafre
2020-08-27 15:21:25 +08:00
Space space = this.searchOne(id);
<aop:aspectj-autoproxy expose-proxy="true"/>
br00k
2020-08-27 19:15:56 +08:00
把当前实例使用 @Lazy 注入,内部方法走 service 调用就可以走代理了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/701813

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX