@NamedQuery(
name=DBConstants.SERVICE_BY_ID, query="select s from Service s where s.id= :id",
hints={
@QueryHint(name = QueryHints.QUERY_RESULTS_CACHE, value = HintValues.TRUE),
@QueryHint(name = QueryHints.QUERY_RESULTS_CACHE_SIZE, value = "500")
})
我在每个查询请求中使用不同的实体管理器。
Query query = em.createNamedQuery(DBConstants.SERVICE_BY_ID);
query.setParameter("id", id);
result = (Service) query.getSingleResult();
这总是从数据库返回数据,但不是从Cache返回。
我如何测试 - >我在数据库中更改了一些列值,当我执行查询时,修改后的值即将到来。理想情况下,它应返回过时数据,因为缓存未刷新或无效。
修订版2:
如果我们尝试缓存命名查询,那么使用多租户感知持久性类将导致问题。怎么样?以下是我认为它的工作方式:
@Cache(
type=CacheType.SOFT,
size=6000,
expiry=600000
)
@Multitenant
@TenantDiscriminatorColumn(...)
@NamedQueries({
@NamedQuery(
name=DBConstants.ALL_SERVICES, query="select s from Service s",
hints={
@QueryHint(name = QueryHints.QUERY_RESULTS_CACHE, value = HintValues.TRUE),
@QueryHint(name = QueryHints.QUERY_RESULTS_CACHE_SIZE, value = "10")
})
})
})
@IdClass(ServicePK.class)
public class Service implements Serializable { ... }
创建EMF:
String tenantID = getTenantID();
properties.put(DBConstants.TENANT_ID_CONTEXT_PROPERTY, tenantID);
properties.put(DBConstants.LINK_SESSION_NAME, "session-" + tenantID);
if(emf == null)
emf = Persistence.createEntityManagerFactory("<PERSISTENCE_UNIT_NAME>", properties);
创建EM:
em = emf.createEntityManager();
在这种情况下,我们的命名查询“ALL_SERVICES”将搜索所有服务,我们希望命名查询缓存根据该查询进行缓存。但是当我们执行这个查询时,EM会将tenantId附加到查询中,即
select s from Service s where s.tenantID = <VALUE>
它缓存在L1缓存的隔离缓存中,并且在您使用相同的EM实例之前可用。 创建新的EM实例时,它会在尝试调用DB上的查询之前检查该条目是否存在于L2缓存中。 L2缓存仅基于我们提到的查询而不是附加的tenantId。这会导致缓存命中未命中,并且呼叫始终进入后端。
现在......我该如何解决这个问题?我可以删除多租户注释并在查询中添加tenantId。我测试了它,它的工作非常好。
但是删除多租户注释会导致很多条件检查手动完成,尤其是当我们依赖其他持久性类时。
我需要一个更好的解决方案。谁能帮忙???