Spring 数据 REST HATEOAS:不是延迟加载
Spring Data REST HATEOS : not lazy loading
问题
我定义了两个实体:School
和 District
。一个区可以有很多学校,一个学校可以属于一个区。
当针对此端点 http://localhost:8080/districts
执行 GET
请求时,我想获取所有学区的列表,而不获取每个学区的一组关联学校。但似乎无论我做什么,hibernate 都会调用数据库来分别为每所学校获取数据。
实体
学校
@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
重复了数百次。
版本:
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'
在你的情况下,你要么必须为地区服务调用创建另一个视图,要么你想尝试 @JSONIGNORE
for schoolList
属性 以使 LazyLoad 生效(我猜您的表示层是 JSON)。
发生的事情是,当您进行地区服务调用时,它当然会返回具有延迟加载的 District
对象,但是一旦您的 POJO 到 JSON 转换由控制器处理,它正在调用 School getter,然后调用 School 对象的进一步方法来创建完整的数据表示,从而导致休眠也加载 school 对象。
更新
在github中添加了示例代码供您参考。
您可以在三个选项中进行选择:
@JsonIgnore
- 将完全忽略任何 serialization/deserialization 的 属性。不确定这是否是您真正想要的。
@JsonManagedReference & @JsonManagedReference
- 将避免 json recursion/Whosebug 由于 hibernate/table 交叉引用结构引起的问题。
@JsonIgnoreProperties
- 另一种避免引用实体 json 递归问题的方法。
注意:FetchType.LAZY
是默认的,所以没有明确说明。
供快速参考的代码片段:
@Getter
@Setter
@Entity
public class District {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
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;
@OneToMany(mappedBy = "district")
//@JsonManagedReference //to avoid JSON recursion solution 1
//@JsonIgnoreProperties("district") //to avoid JSON recursion solution 2
@JsonIgnore
private Set<School> schools;
}
@Getter
@Setter
@Entity
public class School {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique=true, nullable = false)
private Long number;
@Column(nullable = false)
private String name;
private boolean closed;
@Embedded
private ContactInfo contactInfo;
private String gradeLow;
private String gradeHigh;
private int enrollment;
@ManyToOne
@JoinColumn(name = "district_id", nullable = false)
//@JsonBackReference //to avoid JSON recursion solution 1
//@JsonIgnoreProperties("schools") //to avoid JSON recursion solution 2
@JsonIgnore
private District district;
}
看起来你的代码甚至不可用,没有 @JsonIgnore
字段 district
在尝试获取所有可用学校期间你应该收到类似的东西:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No
serializer found for class
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no
properties discovered to create BeanSerializer (to avoid exception,
disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference
chain:
java.util.ArrayList[0]->com.mberazouski.Whosebug.springboothibernate.model.School["district"]->com.mberazouski.Whosebug.springboothibernate.model.District_$$_jvstad5_0["handler"])
at
com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
~[jackson-databind-2.9.6.jar:2.9.6]
但是如果您要添加此注释 - 一切都应该按预期开始工作。所以唯一应该添加的变化应该是:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "district_id")
@JsonIgnore
private District district;
跟踪的结果将是:
2018-06-17 17:27:56.431 DEBUG 25024 --- [nio-8080-exec-1]
org.hibernate.SQL : select school0_.id as
id1_3_, school0_.closed as closed2_3_, school0_.district_id as
district8_3_, school0_.enrollment as enrollme3_3_, school0_.grade_high
as grade_hi4_3_, school0_.grade_low as grade_lo5_3_, school0_.name as
name6_3_, school0_.number as number7_3_ from school school0_
与此相反,如果您将删除懒惰:
@ManyToOne
@JoinColumn(name = "district_id")
private District district;
我们将得到完整的结果:
用于测试的控制器:
import com.mberazouski.Whosebug.springboothibernate.model.School;
import com.mberazouski.Whosebug.springboothibernate.repository.SchoolRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class SchoolController {
@Autowired
SchoolRepository schoolRepository;
@GetMapping("/schools")
public List<School> getAllSchools() {
return schoolRepository.findAll();
}
}
希望建议的更改能够解决您的问题。
祝你好运。
终于弄明白了……为了简单起见,我最初发布这个问题时没有包含所有代码。不幸的是,错误代码不是我最初发布的。
发生了什么事
我为我的 School
对象创建了一个 Projection,并将投影映射到 SchoolRepository
,如下面的代码所示。我 认为 只有在 REST 请求中明确指定时才应用投影(即:/schools?projection=schoolExcerpt
)但显然,投影一直在应用。出于某种原因,District
对象将 SchoolProjection
应用于每个关联的学校 -> 导致 SQL 查询从每个学校单独获取数据,即使使用 @JsonIgore
注释当前的。
我是如何解决问题的
通过简单地删除投影,我能够检索所有 Districts
的列表,而无需进行数千次调用来解析每个关联的学校对象。
@RepositoryRestResource(excerptProjection = SchoolProjection.class) //removing this line solves my problems
public interface SchoolRepository extends CrudRepository<School, Long>{
}
PS
我什至不需要 @JsonIgnore
注释...HATEOAS 足够聪明,不会包含相关对象 - 相反,它包含指向相关对象的链接。
问题
我定义了两个实体:School
和 District
。一个区可以有很多学校,一个学校可以属于一个区。
当针对此端点 http://localhost:8080/districts
执行 GET
请求时,我想获取所有学区的列表,而不获取每个学区的一组关联学校。但似乎无论我做什么,hibernate 都会调用数据库来分别为每所学校获取数据。
实体
学校
@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
重复了数百次。
版本:
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'
在你的情况下,你要么必须为地区服务调用创建另一个视图,要么你想尝试 @JSONIGNORE
for schoolList
属性 以使 LazyLoad 生效(我猜您的表示层是 JSON)。
发生的事情是,当您进行地区服务调用时,它当然会返回具有延迟加载的 District
对象,但是一旦您的 POJO 到 JSON 转换由控制器处理,它正在调用 School getter,然后调用 School 对象的进一步方法来创建完整的数据表示,从而导致休眠也加载 school 对象。
更新
在github中添加了示例代码供您参考。
您可以在三个选项中进行选择:
@JsonIgnore
- 将完全忽略任何 serialization/deserialization 的 属性。不确定这是否是您真正想要的。@JsonManagedReference & @JsonManagedReference
- 将避免 json recursion/Whosebug 由于 hibernate/table 交叉引用结构引起的问题。@JsonIgnoreProperties
- 另一种避免引用实体 json 递归问题的方法。
注意:FetchType.LAZY
是默认的,所以没有明确说明。
供快速参考的代码片段:
@Getter
@Setter
@Entity
public class District {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
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;
@OneToMany(mappedBy = "district")
//@JsonManagedReference //to avoid JSON recursion solution 1
//@JsonIgnoreProperties("district") //to avoid JSON recursion solution 2
@JsonIgnore
private Set<School> schools;
}
@Getter
@Setter
@Entity
public class School {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique=true, nullable = false)
private Long number;
@Column(nullable = false)
private String name;
private boolean closed;
@Embedded
private ContactInfo contactInfo;
private String gradeLow;
private String gradeHigh;
private int enrollment;
@ManyToOne
@JoinColumn(name = "district_id", nullable = false)
//@JsonBackReference //to avoid JSON recursion solution 1
//@JsonIgnoreProperties("schools") //to avoid JSON recursion solution 2
@JsonIgnore
private District district;
}
看起来你的代码甚至不可用,没有 @JsonIgnore
字段 district
在尝试获取所有可用学校期间你应该收到类似的东西:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->com.mberazouski.Whosebug.springboothibernate.model.School["district"]->com.mberazouski.Whosebug.springboothibernate.model.District_$$_jvstad5_0["handler"]) at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.9.6.jar:2.9.6]
但是如果您要添加此注释 - 一切都应该按预期开始工作。所以唯一应该添加的变化应该是:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "district_id")
@JsonIgnore
private District district;
跟踪的结果将是:
2018-06-17 17:27:56.431 DEBUG 25024 --- [nio-8080-exec-1] org.hibernate.SQL : select school0_.id as id1_3_, school0_.closed as closed2_3_, school0_.district_id as district8_3_, school0_.enrollment as enrollme3_3_, school0_.grade_high as grade_hi4_3_, school0_.grade_low as grade_lo5_3_, school0_.name as name6_3_, school0_.number as number7_3_ from school school0_
与此相反,如果您将删除懒惰:
@ManyToOne
@JoinColumn(name = "district_id")
private District district;
我们将得到完整的结果:
用于测试的控制器:
import com.mberazouski.Whosebug.springboothibernate.model.School;
import com.mberazouski.Whosebug.springboothibernate.repository.SchoolRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class SchoolController {
@Autowired
SchoolRepository schoolRepository;
@GetMapping("/schools")
public List<School> getAllSchools() {
return schoolRepository.findAll();
}
}
希望建议的更改能够解决您的问题。
祝你好运。
终于弄明白了……为了简单起见,我最初发布这个问题时没有包含所有代码。不幸的是,错误代码不是我最初发布的。
发生了什么事
我为我的 School
对象创建了一个 Projection,并将投影映射到 SchoolRepository
,如下面的代码所示。我 认为 只有在 REST 请求中明确指定时才应用投影(即:/schools?projection=schoolExcerpt
)但显然,投影一直在应用。出于某种原因,District
对象将 SchoolProjection
应用于每个关联的学校 -> 导致 SQL 查询从每个学校单独获取数据,即使使用 @JsonIgore
注释当前的。
我是如何解决问题的
通过简单地删除投影,我能够检索所有 Districts
的列表,而无需进行数千次调用来解析每个关联的学校对象。
@RepositoryRestResource(excerptProjection = SchoolProjection.class) //removing this line solves my problems
public interface SchoolRepository extends CrudRepository<School, Long>{
}
PS
我什至不需要 @JsonIgnore
注释...HATEOAS 足够聪明,不会包含相关对象 - 相反,它包含指向相关对象的链接。