Java spring@Cacheable如何使用dao调用在服务级别工作
我有以下代码:Java spring@Cacheable如何使用dao调用在服务级别工作,java,spring,spring-boot,Java,Spring,Spring Boot,我有以下代码: @Service public class MyServiceImpl implements MyService { @Autowired private MyDao myDao; @Cacheable("callDao") @Override public MyResultModel callDao(MyCondition condition) { System.out.println("call without cac
@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
方法有什么问题
以下是我的配置:
@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();
}
我是这样称呼这些方法的
@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);
}
}
}
正如所指出的(在他删除的答案中,需要10000个声誉才能看到)和评论中所指出的,您需要在MyCondition
类中实现equals()
和hashCode()
Spring的缓存抽象通过基于参数缓存方法调用的结果来工作。在本例中,您只有一个参数(MyCondition
)。但是,生成的密钥将使用参数的hashCode()
实现
在您的例子中,您没有实现equals()
或hashCode()
,因此每次创建一个新的MyCondition
对象时,它都会有一个不同的hashCode,因此Spring不会知道它缓存了结果
这并不能解释为什么
cacheTest()
方法确实有效。但我想这是因为我们现在没有看到代码(或者您使用了不同的条件,或者发生了其他情况)。PS:我用redis配置缓存。可能是缓存配置的问题。谢谢你的帮助,我的配置已经发布了@DarkCan您可以显示MyCondition的代码吗?另外,如何调用callDao
方法?您是从不同的类/服务调用它还是在同一个服务中调用它?在您的MyCondition
类中实现hashCode
和equals
。非常感谢。我终于解决了我的问题。原因是,我在mybatis受体中修改了mycondition。然后更改redis键。因此,第二次调用无法命中缓存。
@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
-------------------------------------------------------
=======================================================