【问题标题】:Hibernate caching for projections用于投影的休眠缓存
【发布时间】:2020-09-05 03:27:34
【问题描述】:

我使用 JPA 来实现缓存(Hibernate 和 Redis)的持久性。

我有几个包含多列的表。
在大多数情况下,我只需要检索几列。但是,业务逻辑查询包含多个连接和复杂的过滤条件。

我正在考虑使用 JPQL、Criteria API 或本机查询来实现业务逻辑。本机查询最吸引我,因为我可以使用窗口函数和其他特定于 DB 的功能。 我只关心缓存效率。对于包含字段子集(投影)的查询,Hibernate 会使用缓存实体吗?

我相信,不是,唯一的缓存将在查询级别。 因此,对于这种情况,在性能、缓存或其他方面使用 JPQL 或标准 API 没有任何好处……我可以在此处使用直接本机查询,并将“可缓存”参数设置为“真”。

您能否证实或反驳我的理解?

【问题讨论】:

  • 为什么需要缓存?数据库还不够快吗?
  • @SimonMartinelli 我想了解它是如何工作的。

标签: java sql hibernate caching jpql


【解决方案1】:

你是对的,如果你不是在获取实体而是投影,那么实体缓存对你没有帮助。您仍然可以使用查询缓存,但失效的粒度非常粗,因此您可能看不到很大的好处。我建议您避免缓存,除非您别无选择,因为有很多事情可能会出错。当使用适当的索引时,数据库通常足够快以处理所有请求,而且通常只扩展数据库比在顶部实现复杂的缓存更容易。

话虽如此,我只能建议您看一下Blaze-Persistence Entity Views,它允许您将投影建模为接口。

Blaze-Persitence 是 JPA 之上的查询构建器,它支持 JPA 模型之上的许多高级 DBMS 功能(以及窗口函数)。我在它之上创建了实体视图,以允许在 JPA 模型和自定义接口定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您以您喜欢的方式定义您的目标结构,并通过 JPQL 表达式将属性(getter)映射到实体模型。由于属性名称用作默认映射,因此您通常不需要显式映射,因为 80% 的用例是拥有作为实体模型子集的 DTO。

使用窗口函数的实体视图可能看起来像下面这样简单

@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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 2015-07-17
    • 2012-08-06
    • 2017-01-24
    • 1970-01-01
    • 2013-05-31
    • 2012-11-26
    相关资源
    最近更新 更多