我使用 JPA 来实现缓存持久化(Hibernate 和 Redis)。
我有几个包含多列的表。
在大多数情况下,我只需要检索几列。然而,业务逻辑查询包含多个联接和复杂的过滤条件。
我正在考虑使用 JPQL、Criteria API 或 native 查询来实现业务逻辑。 native 查询最吸引我,因为我可以使用窗口函数和其他特定于数据库的功能。 我只关心缓存效率。对于包含字段子集(投影)的查询,Hibernate 会使用缓存实体吗?
我相信,唯一的缓存不是在查询级别。 因此,对于这种情况,使用 JPQL 或标准 API 在性能、缓存或其他方面没有任何好处……我可以在此处使用直接 native 查询,并将“可缓存”参数设置为“true”。
您能否证实或反驳我的理解?
最佳答案
你是对的,如果你不获取实体而是投影,实体缓存将无法帮助你。您仍然可以使用查询缓存,但失效的粒度非常粗,因此您可能看不到很大的好处。我建议您避免缓存,除非您别无选择,因为有很多事情可能会出错。当使用适当的索引时,数据库通常足够快来处理所有请求,并且通常扩展数据库比在顶部实现复杂的缓存更容易。
话虽如此,我只能推荐你看看Blaze-Persistence Entity Views它允许您将投影建模为接口(interface)。
Blaze-Persitence 是基于 JPA 的查询生成器,它支持基于 JPA 模型的许多高级 DBMS 功能(以及窗口函数)。我在其之上创建了实体 View ,以允许在 JPA 模型和自定义接口(interface)定义的模型之间轻松映射,就像类固醇上的 Spring Data Projections 一样。这个想法是,您按照自己喜欢的方式定义目标结构,并通过 JPQL 表达式将属性(getter)映射到实体模型。由于属性名称用作默认映射,因此您通常不需要显式映射,因为 80% 的用例都具有作为实体模型子集的 DTO。
使用窗口函数的实体 View 可能看起来像下面一样简单
@EntityView(Order.class)
public interface OrderTotalPriceDTO {
Long getId();
String getCustomer();
@Mapping("SUM(orderLines.totalPrice)")
BigDecimal getTotalPrice();
@Mapping("SUM(SUM(orderLines.totalPrice)) OVER (ORDER BY orderDate)")
BigDecimal getCummulativeTotalPrice();
}
Spring Data 集成允许您像 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
关于java - 用于投影的 Hibernate 缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61884715/