java - 用于投影的 Hibernate 缓存

标签 java sql hibernate caching jpql

我使用 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/

相关文章:

mysql - MySQL中外键与复合主键的关系

基于连接拆分表的 SQL 语句

java - session.clear() 是必要的吗?

hibernate - 在 entitymanager 上使用 unwrap 方法获取 native hibernate session 后,我是否必须同时关闭这两个 session ?

java - hibernate 中的魔法 npe

java - Android ListView - 第 n 个元素后的分隔线

java - hibernate 时异常

java - 我怎样才能打破 FileChannel#transferFrom 循环?

java - mysql中数据库的创建和删除

php - 我的查询不起作用。我能做些什么?