繁体   English   中英

如何在grails中缓存(整个表或Domain.list()方法的结果)?

[英]How to cache (entire table or results of Domain.list() method) in grails?

我有一个小表SYMBOLS,用于填充ui上的下拉列表。 由于此表主要包含静态数据,因此我想缓存其内容。

我的问题是,每次调用Symbol.list()方法时,都会在数据库上执行查询。

域类:

package com.perseus.ui.model

class Symbol implements Serializable, Comparable<Symbol> {

private static final long serialVersionUID = 1L;

String exchange
String symbol
String description
int index

static constraints = {
    exchange(nullable:false, blank: false)
    symbol(nullable:false, blank: false)
    description(nullable:false, blank: false)
}

static mapping = {
    id composite: ['exchange', 'symbol']
    table 'Symbols'
    cache 'read-only'
}

String toString() {
    return description
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
            + ((exchange == null) ? 0 : exchange.hashCode());
    result = prime * result + ((symbol == null) ? 0 : symbol.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Symbol other = (Symbol) obj;
    if (exchange == null) {
        if (other.exchange != null)
            return false;
    } else if (!exchange.equals(other.exchange))
        return false;
    if (symbol == null) {
        if (other.symbol != null)
            return false;
    } else if (!symbol.equals(other.symbol))
        return false;
    return true;
}

@Override
public int compareTo(Symbol o) {
    int result = 0
    if(this.index)
        result = -1
    else if(o.index) {
        result = 1
    } else {
        result = this.symbol.compareTo(o.symbol)
    }
    return result;
}


}

resources.groovy

// Place your Spring DSL code here
beans = {
xmlns cache: 'http://www.springframework.org/schema/cache'
xmlns aop: 'http://www.springframework.org/schema/aop'

importBeans('classpath:config/beans.xml')

cache.'advice'(id: 'symbolCacheAdvice',
        'cache-manager': 'grailsCacheManager') {
        caching(cache: 'symbols') {
            cacheable(method: 'list')
        }
    }

aop.config {
    advisor('advice-ref': 'symbolCacheAdvice',
        pointcut: 'execution(* com.perseus.ui.model.Symbol.*(..))')
}

}

UI元素: <g:select name="symbol" from="${Symbol.list(readOnly: true)}" optionKey="symbol" />

我尝试了以下选项,但它们似乎都不起作用:

  1. 休眠二级缓存:缓存了对象,但是Symbol.list()总是命中数据库。
  2. 启用查询缓存:没有帮助
  3. 标记Symbols.list()方法@Cachable:令人惊讶的是,即使这样也没有用。 请参阅resources.groovy。

我认为这是非常常见的用例,实现此目的的最佳方法是什么? 一种明显的解决方案是手动缓存它,但这听起来不太好。

通常,请避免对GORM查询结果使用缓存插件-Hibernate的1级和2级缓存非常可靠,并且可以防止陈旧数据,因为当有可能这些结果可能受到更改的影响时,它们会刷新缓存的数据。 但是,如果直接使用Ehcache或Spring Cache或Grails插件之类的包装API,则必须知道何时使数据无效,这可能是一个难题。

如果您打算仅通过list()方法访问缓存的数据,这是有意义的,因为它们全部都在内存中,那么您需要使用查询缓存的变体,并且必须在DataSource.groovy中启用它:

hibernate {
   cache.use_second_level_cache = true
   cache.use_query_cache = true
   ...
}

list()没有缓存选项,您可以运行具有以下条件的等效条件查询:

def symbols = Symbol.createCriteria().list {
   cache true
}

如果Symbol.get(id) ID访问项目,请运行查询以获取所有ID,然后在启动时循环遍历,并为每个Symbol.get(id)调用Symbol.get(id) 各个实例都缓存在自己的缓存中,而不是查询缓存中,因此不太可能使它们早日失效。

还要注意,您需要配置基础缓存实现,并配置缓存大小,内存中的元素,溢出到磁盘等。Ehcache中的默认TTL为120秒-仅2分钟。 但是,如果您很少或从未编辑/创建/删除这些文件,则可以根据需要进行缓存。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM