我有很多JPA DAO正在寻求迁移到Spring Data JPA。我的一些DAOS设置了二级/查询缓存。
我有一个流程,我只在查询中检索ID,然后使用findByID()
查找实体。这样,只有id在不同的查询缓存中相乘,整个实体都在二级缓存中。
示例:
@NamedQuery(name = "SystemUser.findByEmail",
query = "SELECT u.id FROM SystemUser u WHERE email=:email"),
…
public SystemUser findByEmail(String email) {
TypedQuery<Long> q = getEntityManager().createNamedQuery("SystemUser.findByEmail", Long.class);
q.setParameter("email", email);
q.setHint("org.hibernate.cacheable", true);
q.setHint("org.hibernate.cacheRegion", "query.systemUser");
List<Long> res = q.getResultList();
if (res != null && res.size() > 0) {
return findById(res.get(0));
}
return null;
}
我还有几个findBy…
- 方法,所有这些都是这样做的。感觉这是保持缓存内存消耗的好方法。
我对Spring Data JPA业务有点新意,但我看不出如何在这里实现这个目标? @Cacheable
注释似乎只处理查询缓存,我会在每个查询缓存中复制实体吗?
有没有办法用Spring Data做到这一点?指针将非常感激。
答案 0 :(得分:4)
在Spring Data JPA中只需创建一个findByEmail
方法,Spring Data JPA将找到您的命名查询或自己创建一个。
public class SystemUserRepository extends CrudRepository<SystemUser, Long> {
SystemUser findByEmail(String email);
}
应该只需要执行查询和所需的结果。现在使用@QueryHints
,您可以添加您现在正在设置的提示。
public class SystemUserRepository extends CrudRepository<SystemUser, Long> {
@QueryHints(
@QueryHint(name="org.hibernate.cacheable", value="true"),
@QueryHint(name="org.hibernate.cacheRegion", value="query.systemUser") )
SystemUser findByEmail(String email);
}
结果将被缓存,用户仍将来自二级缓存(如果可用,否则创建)。假设您的实体当然是@Cacheable
。
可以找到关于2个不同缓存如何协同工作的精彩内容here。关于查询缓存如何工作的小片段。
查询缓存在概念上看起来像一个哈希映射,其中密钥由查询文本和参数值组成,该值是与查询匹配的实体ID列表 :
如果您想要更复杂的逻辑(并且真正实现您所做的优化),您始终可以实施own repository。