【问题标题】:Custom hibernate second level cache name lookup自定义休眠二级缓存名称查找
【发布时间】:2017-04-25 22:52:50
【问题描述】:

我正在为实体使用带有二级缓存的 Spring Boot,例如

@Entity
@Table(name = "customer")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Customer implements Serializable {
  ....
}

这按预期工作,但现在我必须将应用程序转换为多租户版本。每个租户都有自己的数据库,我们使用ThreadLocal 来存储当前租户,AbstractRoutingDataSource 用于路由到租户的数据库。如果二级缓存已关闭,则此方法有效。

让二级缓存也能正常工作会很好。问题似乎是缓存名称,它是实体的 FQCN。由于缓存不是租户或数据库感知的,因此每个租户使用相同的缓存。

为此,我们使用ThreadLocal 来解析当前租户可以简单地通过

TenantContext.getCurrentTenant();

并返回租户名称。

我们使用 EhCache,它由 Spring 缓存抽象支持:

@Bean
public CacheManager cacheManager() {
    net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.create();
    EhCacheCacheManager ehCacheManager = new EhCacheCacheManager();
    ehCacheManager.setCacheManager(cacheManager);
    return ehCacheManager;
}

是否可以截取cache-name的生成,从而使用当前的tenant name代替FQCN,每次insert/lookup/evict都解析这个tenant-aware-cache-name?

【问题讨论】:

  • 可能你的 Hibernate 不知道你期望它是多租户的。否则你的缓存会起作用。你先读过这个吗? docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch16.html
  • 是的,我知道。我们知道 hibernate 的多租户支持,但我们必须解决其他“问题”(例如,使用 liquibase、spring data 或 elasticsearch ......)所以我们不能使用它并选择了另一种解决方案。一个正确的缓存名称解析器可以解决这个问题......

标签: java spring hibernate caching


【解决方案1】:

为了拦截缓存名称的生成,一种方法是覆盖EhCacheCacheManager 的方法getCache(String name),如下所示:

@Bean
public CacheManager cacheManager() {
    net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.create();
    EhCacheCacheManager ehCacheManager = new EhCacheCacheManager(){
        @Override
        public Cache getCache(String name) {
            String tenantId = TenantContext.getCurrentTenant();
            return super.getCache(String.format("%s:%s", tenantId, name));
        }
    };
    ehCacheManager.setCacheManager(cacheManager);
    return ehCacheManager;
}

【讨论】:

    猜你喜欢
    • 2010-10-20
    • 2015-10-23
    • 2017-07-05
    • 2011-07-08
    • 1970-01-01
    • 2017-10-07
    • 2019-04-02
    • 2010-10-29
    相关资源
    最近更新 更多