spring @Cacheable 如何通过 dao 调用在服务级别工作 [英] How can spring @Cacheable work in service level with a dao call
问题描述
我有以下代码:
@Service
public class MyServiceImpl implements MyService {
@Autowired
private MyDao myDao;
@Cacheable("callDao")
@Override
public MyResultModel callDao(MyCondition condition) {
System.out.println("call without cache");
return myDao.call(condition);
}
@Cacheable("cacheTest")
@Override
public MyResultModel cacheTest(MyCondition condition) {
System.out.println("call without cache");
return new MyResultModel(someProperties);
}
}
然而,callDao
缓存不起作用,因为该方法仍然一直调用数据库.另一方面,cacheTest
确实工作正常.我的 callDao
方法有什么问题?
However, the callDao
cache does not work since the method still calls the DB all the time. On the other hand, cacheTest
does work properly. What is wrong with my callDao
method?
这是我的配置:
@Bean
public CacheManager cacheManager(RedisCacheManagerConfiguration configuration,
@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(configuration.getDefaultExpiration());
cacheManager.setUsePrefix(configuration.isUsePrefix());
cacheManager.setLoadRemoteCachesOnStartup(configuration.isLoadRemoteCachesOnStartup());
return cacheManager;
}
@Bean
public RedisTemplate<String, String> stringRedisTemplate(
@Qualifier("stringRedisSerializer") RedisSerializer<String> keySerializer,
@Qualifier("stringRedisSerializer") RedisSerializer<String> valueSerializer,
@Qualifier("stringRedisSerializer") RedisSerializer<String> hashKeySerializer,
@Qualifier("stringRedisSerializer") RedisSerializer<String> hashValueSerializer,
JedisConnectionFactory connectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setKeySerializer(keySerializer);
template.setValueSerializer(valueSerializer);
template.setHashKeySerializer(hashKeySerializer);
template.setHashValueSerializer(hashValueSerializer);
template.setConnectionFactory(connectionFactory);
template.afterPropertiesSet();
return template;
}
@Bean(name = "stringRedisSerializer")
public StringRedisSerializer stringRedisSerializer() {
return new StringRedisSerializer();
}
我只配置了CacheManager
和RedisTemplate
.我还添加了 @EnableCaching
注释.
I only configured CacheManager
and RedisTemplate
. I also added the @EnableCaching
annotation.
Hear is MyCondition:
Hear is MyCondition:
public class MyCondition implements Serializable {
/**
* @since JDK 1.8
*/
private static final long serialVersionUID = 6262123870251938833L;
private String guid;
private Boolean isDelete;
public String getGuid() {
return guid;
}
public void setGuid(String guid) {
this.guid = guid;
}
public Boolean getIsDelete() {
return isDelete;
}
public void setIsDelete(Boolean isDelete) {
this.isDelete = isDelete;
}
}
听说我如何调用这些方法
Hear is how i call these method
@EnableCaching
@EnableAutoConfiguration
@ComponentScan({ "com.mypackage" })
@SpringBootApplication
public class Application extends ContextIdApplicationContextInitializer {
public static ConfigurableApplicationContext ctx;
public static void main(String[] args) throws Exception {
ctx = SpringApplication.run(Application.class, args);
MyService myService = ctx.getBean(MyService.class);
for (int i = 0; i < 10; i++) {
MyCondition condition = new ConditionForRideCard();
condition.setGuid("adsgsfdhgsfgfdghhsdfgfadf");
myService.callDao(condition);
System.out.println("-------------------------------------------------------");
myService.cacheTest(condition);
System.out.println("=======================================================");
Thread.sleep(1000);
}
}
}
我得到这样的结果:
call without cache
-------------------------------------------------------
call without cache
=======================================================
call without cache
-------------------------------------------------------
=======================================================
call without cache
-------------------------------------------------------
=======================================================
call without cache
-------------------------------------------------------
=======================================================
call without cache
-------------------------------------------------------
=======================================================
call without cache
-------------------------------------------------------
=======================================================
call without cache
-------------------------------------------------------
=======================================================
call without cache
-------------------------------------------------------
=======================================================
call without cache
-------------------------------------------------------
=======================================================
call without cache
-------------------------------------------------------
=======================================================
推荐答案
正如 StuPointerException 指出的(在他删除的答案中,需要10000 声望)和 M.注释中的Deinum,您需要在MyCondition
类中同时实现equals()
和hashCode()
.
As StuPointerException pointed out (in his deleted answer, requires 10000 reputation to see) and M. Deinum in the comments, you need to implement both equals()
and hashCode()
in your MyCondition
class.
Spring 的缓存抽象通过基于参数缓存方法调用的结果来工作.在这种情况下,您只有一个参数 (MyCondition
).但是,生成的密钥将使用参数的 hashCode()
实现.
Spring's cache abstraction works by caching the result of the method call based on the arguments. In this case, you have only one argument (MyCondition
). However, the generated key will use the hashCode()
implementation of the parameters.
在你的情况下,你没有实现 equals()
也没有实现 hashCode()
,所以每次你创建一个新的 MyCondition
对象,它将具有不同的哈希码,因此,Spring 不会知道它的结果已缓存.
In your case, you didn't implement equals()
nor hashCode()
, so every time you create a new MyCondition
object, it will have a different hashcode, and thus, Spring won't know that it has its result cached.
这并不能解释为什么 cacheTest()
方法确实有效.但我想这是因为我们现在没有看到代码(要么您使用了不同的条件,要么发生了其他事情).
This doesn't explain why the cacheTest()
method does work though. But I guess this is due to code we're not seeing right now (either you're using a different condition, or there's something else going on).
这篇关于spring @Cacheable 如何通过 dao 调用在服务级别工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!