我有以下代码:
@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
缓存不起作用,因为该方法仍然一直调用DB。另一方面,cacheTest
确实可以正常工作。我的callDao
方法出了什么问题?
这是我的配置:
@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
注释。
听到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;
}
}
听我称之为这些方法
@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
-------------------------------------------------------
=======================================================
答案 0 :(得分:0)
正如StuPointerException所指出的那样(在他删除的答案中需要获得10000点声望)和评论中的M. Deinum,您需要同时实施equals()
和hashCode()
你的MyCondition
课程。
Spring的缓存抽象通过基于参数缓存方法调用的结果来工作。在这种情况下,您只有一个参数(MyCondition
)。但是,生成的密钥将使用参数的hashCode()
实现。
在您的情况下,您没有实现equals()
也没有hashCode()
,因此每次创建新的MyCondition
对象时,它都会有不同的哈希码,因此, Spring不知道它的结果是缓存的。
这并不能解释为什么cacheTest()
方法确实有效。但我想这是由于我们现在没有看到的代码(要么您使用不同的条件,要么还有其他事情发生)。