【问题标题】:Using Spring Query Methods JPA to efficiently query DB without multiple SELECT statements使用 Spring Query Methods JPA 高效查询 DB,无需多个 SELECT 语句
【发布时间】:2019-04-18 16:13:05
【问题描述】:

我有一个实体,它具有简单的字符串列以及许多 ElementCollections(列表和地图)。我注意到查看我的 postgres 日志, PostGres 在查询此实体时连续执行一堆 SELECT 查询以获取所有 ElementCollections。

为了提高效率,我想用一些内部 JOIN 执行一个 SELECT 查询可能会更好地避免所有单独的 SELECT 查询。有没有办法在不使用所有 INNER JOIN 手动编写非常冗长的选择查询的情况下做到这一点?

我一直在寻找 FetchTypes 和 Spring QueryData 语言以及 DTO 投影,但我想可能会有更直接的方法。我一直认为理所当然的好处是,如果我添加一个新字段,那么我将不得不继续更新我的查询,如果 Spring 正在为我生成查询,那么我就不必做任何事情。

// Person.java

@Entity
public Person {

    @Id
    long personId;

    @Column
    String firstName;

    @Column
    String lastName;

    @ElementCollections
    Set<String> someField;

    @ElementCollections
    Map<String, String> otherField;

    @ElementCollections
    Set<String> anotherField;

    @ElementCollections
    Map<String, String> yetAnotherField;
}

现在发生的事情是

SELECT firstName, lastName FROM Person WHERE personId=$1
SELECT someField FROM Person_SomeField WHERE someField.personId=$1
SELECT otherField.key otherField.value FROM Person_OtherField WHERE otherField.personId=$1

所有 ElementCollections 表都会继续这种情况,这会导致大量查询。

【问题讨论】:

    标签: spring hibernate spring-boot jpa spring-data-jpa


    【解决方案1】:

    将您的注释更改为@ElementCollection(fetch = FetchType.EAGER)

    听起来这些字段正在被延迟加载(Hibernate 正在等待它们被访问以加载它们),这会导致您看到 N+1 个查询。 LAZY 加载是此类成员的默认行为,这是有道理的,因为加载它并不便宜。但是,如果您总是希望加载这些成员,则将其设置为 EAGER 是有意义的。将 fetch 设置为 EAGER 将强制 Hibernate 将它们与实体本身一起加载。这是@ElementCollectionfetch 选项的文档:

    (可选)该集合是应该延迟加载还是必须 急切地取来。 EAGER 战略是对 集合元素必须是持久性提供程序运行时 急切地取来。 LAZY 策略是对持久性的暗示 提供程序运行时。

    【讨论】:

      猜你喜欢
      • 2020-04-18
      • 2016-01-04
      • 2022-11-21
      • 1970-01-01
      • 2017-07-28
      • 2020-09-14
      • 2017-03-13
      • 2020-05-20
      • 2021-08-27
      相关资源
      最近更新 更多