本文介绍了Spring Data REST HATEOS:不是延迟加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义了两个实体:学校.一个地区可以有很多学校,而一所学校可以属于一个地区.
在对此端点 http://localhost:8080/districts 执行 GET 请求时,我想获取所有学区的列表,而无需获取每个学区的关联学校集.但这似乎不管我做什么,休眠方式都是通过数据库调用来分别获取每个学校的数据.

I have two entities defined: School and District. A district can have many schools and a school can belong to one district.
When executing a GET request against this endpoint http://localhost:8080/districts I would like to get a list of all the districts WITHOUT fetching each district's set of associated schools. But it seems like no matter what I do, hibernate is making DB calls to fetch data for each school individually.

@Getter
@Setter
@NoArgsConstructor
@Entity
public class School {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull
    @Column(unique=true)
    private Long number;

    @NotNull
    @Column
    private String name;

    @NotNull
    private boolean closed;

    @Embedded
    private ContactInfo contactInfo;

    private String gradeLow;
    private String gradeHigh;
    private int enrollment;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "district_id")
    private District district;

}

@Getter
@Setter
@NoArgsConstructor
@Entity
public class District {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(unique = true)
    private Integer number;

    private String  name;
    private String  type;
    private int     enrollment;
    private Date    updated;

    @Embedded
    private ContactInfo contactInfo;

    @Getter(AccessLevel.NONE)
    @JsonIgnore
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "district")
    private Set<School> schoolList;

}

日志输出

SELECT district0_.id          AS id1_5_,
       district0_.city        AS city2_5_,
       district0_.email       AS email3_5_,
       district0_.fax         AS fax4_5_,
       district0_.first_name  AS first_na5_5_,
       district0_.last_name   AS last_nam6_5_,
       district0_.name_prefix AS name_pre7_5_,
       district0_.phone       AS phone8_5_,
       district0_.state       AS state9_5_,
       district0_.street      AS street10_5_,
       district0_.title       AS title11_5_,
       district0_.website     AS website12_5_,
       district0_.zip         AS zip13_5_,
       district0_.enrollment  AS enrollm14_5_,
       district0_.NAME        AS name15_5_,
       district0_.number      AS number16_5_,
       district0_.type        AS type17_5_,
       district0_.updated     AS updated18_5_
FROM   district district0_

SELECT schoollist0_.district_id AS distric20_7_0_,
       schoollist0_.id          AS id1_7_0_,
       schoollist0_.id          AS id1_7_1_,
       schoollist0_.closed      AS closed2_7_1_,
       schoollist0_.city        AS city3_7_1_,
       schoollist0_.email       AS email4_7_1_,
       schoollist0_.fax         AS fax5_7_1_,
       schoollist0_.first_name  AS first_na6_7_1_,
       schoollist0_.last_name   AS last_nam7_7_1_,
       schoollist0_.name_prefix AS name_pre8_7_1_,
       schoollist0_.phone       AS phone9_7_1_,
       schoollist0_.state       AS state10_7_1_,
       schoollist0_.street      AS street11_7_1_,
       schoollist0_.title       AS title12_7_1_,
       schoollist0_.website     AS website13_7_1_,
       schoollist0_.zip         AS zip14_7_1_,
       schoollist0_.district_id AS distric20_7_1_,
       schoollist0_.enrollment  AS enrollm15_7_1_,
       schoollist0_.grade_high  AS grade_h16_7_1_,
       schoollist0_.grade_low   AS grade_l17_7_1_,
       schoollist0_.NAME        AS name18_7_1_,
       schoollist0_.number      AS number19_7_1_
FROM   school schoollist0_
WHERE  schoollist0_.district_id = ?

SELECT schoollist0_.district_id AS distric20_7_0_,
       schoollist0_.id          AS id1_7_0_,
       schoollist0_.id          AS id1_7_1_,
       schoollist0_.closed      AS closed2_7_1_,
       schoollist0_.city        AS city3_7_1_,
       schoollist0_.email       AS email4_7_1_,
       schoollist0_.fax         AS fax5_7_1_,
       schoollist0_.first_name  AS first_na6_7_1_,
       schoollist0_.last_name   AS last_nam7_7_1_,
       schoollist0_.name_prefix AS name_pre8_7_1_,
       schoollist0_.phone       AS phone9_7_1_,
       schoollist0_.state       AS state10_7_1_,
       schoollist0_.street      AS street11_7_1_,
       schoollist0_.title       AS title12_7_1_,
       schoollist0_.website     AS website13_7_1_,
       schoollist0_.zip         AS zip14_7_1_,
       schoollist0_.district_id AS distric20_7_1_,
       schoollist0_.enrollment  AS enrollm15_7_1_,
       schoollist0_.grade_high  AS grade_h16_7_1_,
       schoollist0_.grade_low   AS grade_l17_7_1_,
       schoollist0_.NAME        AS name18_7_1_,
       schoollist0_.number      AS number19_7_1_
FROM   school schoollist0_
WHERE  schoollist0_.district_id = ?

SELECT schoollist0_.district_id AS distric20_7_0_,
       schoollist0_.id          AS id1_7_0_,
       schoollist0_.id          AS id1_7_1_,
       schoollist0_.closed      AS closed2_7_1_,
       schoollist0_.city        AS city3_7_1_,
       schoollist0_.email       AS email4_7_1_,
       schoollist0_.fax         AS fax5_7_1_,
       schoollist0_.first_name  AS first_na6_7_1_,
       schoollist0_.last_name   AS last_nam7_7_1_,
       schoollist0_.name_prefix AS name_pre8_7_1_,
       schoollist0_.phone       AS phone9_7_1_,
       schoollist0_.state       AS state10_7_1_,
       schoollist0_.street      AS street11_7_1_,
       schoollist0_.title       AS title12_7_1_,
       schoollist0_.website     AS website13_7_1_,
       schoollist0_.zip         AS zip14_7_1_,
       schoollist0_.district_id AS distric20_7_1_,
       schoollist0_.enrollment  AS enrollm15_7_1_,
       schoollist0_.grade_high  AS grade_h16_7_1_,
       schoollist0_.grade_low   AS grade_l17_7_1_,
       schoollist0_.NAME        AS name18_7_1_,
       schoollist0_.number      AS number19_7_1_
FROM   school schoollist0_
WHERE  schoollist0_.district_id = ?

SELECT schoollist0_.district_id AS distric20_7_0_,
       schoollist0_.id          AS id1_7_0_,
       schoollist0_.id          AS id1_7_1_,
       schoollist0_.closed      AS closed2_7_1_,
       schoollist0_.city        AS city3_7_1_,
       schoollist0_.email       AS email4_7_1_,
       schoollist0_.fax         AS fax5_7_1_,
       schoollist0_.first_name  AS first_na6_7_1_,
       schoollist0_.last_name   AS last_nam7_7_1_,
       schoollist0_.name_prefix AS name_pre8_7_1_,
       schoollist0_.phone       AS phone9_7_1_,
       schoollist0_.state       AS state10_7_1_,
       schoollist0_.street      AS street11_7_1_,
       schoollist0_.title       AS title12_7_1_,
       schoollist0_.website     AS website13_7_1_,
       schoollist0_.zip         AS zip14_7_1_,
       schoollist0_.district_id AS distric20_7_1_,
       schoollist0_.enrollment  AS enrollm15_7_1_,
       schoollist0_.grade_high  AS grade_h16_7_1_,
       schoollist0_.grade_low   AS grade_l17_7_1_,
       schoollist0_.NAME        AS name18_7_1_,
       schoollist0_.number      AS number19_7_1_
FROM   school schoollist0_
WHERE  schoollist0_.district_id = ?

....

如上所述,尽管将schoolList配置为延迟加载,但 SELECT FROM school 却重复了数百次.

The SELECT FROM school as seen above, repeats hundreds of times despite having the schoolList configured as a lazy load.

版本:

springBootVersion = '1.4.2.RELEASE'
hibernate-core:5.0.11
'org.springframework.boot:spring-boot-starter-data-jpa'
'org.springframework.boot:spring-boot-starter-data-rest'
'org.springframework.boot:spring-boot-starter-web'
'org.springframework.boot:spring-boot-starter-actuator'
'org.springframework.boot:spring-boot-starter-hateoas'
'org.springframework.boot:spring-boot-starter-security'

推荐答案

最后想出了这一点...为了简单起见,当我最初发布此问题时,我并未包括所有代码.不幸的是,错误的代码并不是我最初发布的.

Finally figured this out ... I didn't include all of the code when I originally posted this question for simplicity sake. Unfortunately, the erroneous code was not something I originally posted.

我创建了一个 Projection 作为我的 School 对象,并将投影映射到 SchoolRepository ,如下面的代码所示.我认为仅在REST请求中明确指定投影时才应用投影(即:/schools?projection = schoolExcerpt ),但是显然,投影一直在被应用.出于某种原因, District 对象将 SchoolProjection 应用于每个关联的学校->导致SQL查询以单独的方式从每个学校获取数据,即使使用 @存在JsonIgore 批注.

I had created a Projection for my School object and mapped the projection to the SchoolRepository as shown in the below code. I thought the projection was only applied when explicitly specified in a REST request (ie : /schools?projection=schoolExcerpt) But apparently, the projection was getting applied all the time. And for some reason, the District object was applying the SchoolProjection to each associated school -> resulting in SQL queries to fetch data form each school individually even with the @JsonIgore annotation present.

通过简单地删除投影,我能够检索所有 Districts 的列表,而无需进行数千次调用来解决每个关联的学校对象.

By simply removing the projection I was able to retrieve a list of all Districts without making thousands of calls to resolve each associated school object.

@RepositoryRestResource(excerptProjection = SchoolProjection.class)  //removing this line solves my problems
public interface SchoolRepository extends CrudRepository<School, Long>{

}

PS

实际上我什至不需要 @JsonIgnore 批注... HATEOAS非常聪明,不包含相关对象-而是包含了指向相关对象的链接.

PS

I don't actually even need the @JsonIgnore annotation... HATEOAS is smart enough to not include related objects - instead it includes links to related objects.

这篇关于Spring Data REST HATEOS:不是延迟加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 05:04