在 Spring 中将 @Cacheable 用于非参数方法

Posted

技术标签:

【中文标题】在 Spring 中将 @Cacheable 用于非参数方法【英文标题】:Use @Cacheable for non-argument method in Spring 【发布时间】:2012-07-08 13:07:22 【问题描述】:

我正在使用 Spring 缓存 API,但遇到了一个问题: 我有一个带有 CRUD 操作的 Dao 类,我想做的就是缓存一个无参数方法,它返回一个对象映射(键 - id,值 - 实体)

class Dao implements IDao<Entity>

    public Map<Integer, Entity> getAllEntities() /* retreiving from DB */ 

    public Entity getEntityByKey(Object key)  ... 

    public void insert(Entity entity)...

    public void update(Entity entity)...

    public void delete(Entity entity)...


谁能告诉我如何准确(和正确地)缓存 getAllEntities() 方法以获取实体,缓存 getEntityByKey 以按键获取实体,并且还能够在我执行创建、更新或删除操作时更新缓存? 是否可以在更新后使用方法 getAllEntities 的可缓存版本(使用操作插入、更新、删除)?

【问题讨论】:

顺便说一句 - 如果这是您的应用程序中普遍关心的问题,您是否考虑过使用 Hibernate 和它的二级缓存? 不,我使用 jdbcTemplate 并且没有使用 Hibernate 的能力 Spring 3.1 Cache Abstraction without parameters的可能重复 【参考方案1】:

试试这个

class Dao implements IDao<Entity>

    @Cacheable(value = "entity.all")
    public Map<Integer, Entity> getAllEntities() /* retreiving from DB */ 

    @Cacheable(value = "entity.item", key="#p0")
    public Entity getEntityByKey(Object key)  ... 

    @CacheEvict(value = "entity.all", "entity.item", allEntries=true)
    public void insert(Entity entity)...

    @CacheEvict(value = "entity.all", "entity.item", allEntries=true)
    public void update(Entity entity)...

    @CacheEvict(value = "entity.all", "entity.item", allEntries=true)
    public void delete(Entity entity)...


【讨论】:

感觉spring的缓存机制还有改进的空间。例如@CacheEvict 的 allEntries=true 适用于所有缓存。 allEntries=true 对于“entity.all”和“entity.item”。更好的控制是“entity.all”的所有条目,“entity.item”只有一个项目。 没用。如果我运行 getAllEntities() 它与 DB 一起工作(它是预期的)。然后,我再次运行 insert 方法和之后 - getAllEntities(),但此时此方法不会返回我的 cahced 版本,它会再次开始使用 DB。 这里最重要的是调用 getAllEntities() 或 getEntityByKey() 必须始终返回一个缓存版本,无论进行插入、更新或删除操作。有可能吗?也许使用 EhCache 或有其他一些解决方法? 多次调用 getAllEntities() 是命中数据库还是只命中第一个? 我认为有一个“阻塞”/“非阻塞”配置,返回一个陈旧的缓存,同时构建一个新的。那是你要的吗?例如。你运行你的电话,它击中了数据库。你再打电话。它命中缓存。你做更新。你再打电话。它返回缓存的结果,但在后台它会命中数据库(用于下一次调用)。您再次调用,它会返回新结果,但已缓存(在调用之前检索)

以上是关于在 Spring 中将 @Cacheable 用于非参数方法的主要内容,如果未能解决你的问题,请参考以下文章

Spring @Cacheable 对 @Scope("prototype") 实例唯一

@Cacheable "注解类型不适用于这种声明"

java缓存机制(上) map和spring注解@Cacheable

Spring中@Cacheable的用法

Spring 缓存注解@Cacheable的用法

如何让 Spring @Cacheable 在 AspectJ 方面工作?