使用Spring Query Methods JPA可以有效地查询数据库,而无需多个SELECT语句

时间:2019-04-18 16:13:05

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

我有一个实体,该实体具有简单的String列以及许多ElementCollections(列表和映射)。我注意到查看我的postgres日志时,查询该实体时PostGres正在连续执行一堆SELECT查询以获取所有ElementCollections。

为了提高效率,我想用一些内部JOIN进行一个SELECT查询可能会更好,以避免所有单独的SELECT查询。有没有一种方法可以不用所有INNER JOIN手动编写一个非常冗长的select查询?

我一直在研究FetchTypes和Spring QueryData语言以及DTO Projection,但我想可能会有更直接的方法。我一直想当然的好处是,如果我添加一个新字段,则明确地执行JOIN,那么我将不得不继续更新查询,如果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表,这种情况继续存在,从而导致大量查询。

1 个答案:

答案 0 :(得分:0)

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

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

  

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