spring @Cacheable 如何通过 dao 调用在服务级别工作 [英] How can spring @Cacheable work in service level with a dao call

查看:25
本文介绍了spring @Cacheable 如何通过 dao 调用在服务级别工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

@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();
}

我只配置了CacheManagerRedisTemplate.我还添加了 @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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆