如何正确公开延迟加载多个字段,以便用户GET
/ PATCH
/ POST
/ DELETE
Spring Data REST中的许多实体关系?
例如,给定Student
实体和Teacher
实体受多对多关系约束,使用以下POJO:
@Entity
public class Teacher { // owner of bidirectional relationship
@Id
private int id;
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "teacher_student",
joinColumns = @JoinColumn(name = "teacher_id"),
inverseJoinColumns = @JoinColumn(name = "student_id"))
private Set<Student> students;
// Constructor, getters/setters...
}
@Entity
public class Student {
@Id
private int id;
private String name;
@ManyToMany(mappedBy = "students", fetch = FetchType.LAZY)
private Set<Teacher> teachers;
// Constructor, getters/setters...
}
为实体提供存储库:
@RepositoryRestResource(path = "teacher")
public interface TeacherRepository extends CrudRepository<Teacher, int> {}
// similar repository for student
当我发送GET
给localhost:8080 /老师时,我得到:
"_embedded": {
"teacher": [
{
"name": "Bill Billie",
"_links": {
"self": { "href": "http://localhost:8080/teacher/1" },
"teacher": { ... },
"students": { "href": "http://localhost:8080/teacher/1/students" }
}},
(more teachers here...)
]
}
...
但是,当我尝试GET
到http://localhost:8080/teacher/1/students时,我得到 404 Not Found ,即使老师&#34; Bill Billie&#34; 让学生在数据库中与他相关联。
有趣的是,如果我将FetchType
更改为FetchType.EAGER
,一切正常,我可以执行预期的GET
,PATCH
等。 是什么赋予了?这可能是一个错误,还是我搞砸了什么?
tl; dr许多关系没有通过延迟抓取正确公开,但可以通过急切提取工作。我怎样才能懒惰地使用它?
编辑:如果重要,我使用Spring 4.2.6和Spring Boot 1.3.5,OpenJPA 2.4.1作为我的JPA提供者。
答案 0 :(得分:1)
嗯我不确定为什么它不会自动提取更有经验的人会问这个问题,但是您可以为每个查询指定使用HQL连接提取的手动提取。
select x from X left join fetch x.y y
完成此工作后,您可以使用专门创建的控制器覆盖您的get语句,如下所述:Spring Data REST: Override repository method on the controller
我认为可能值得尝试的其他选项是在Spring数据存储库中添加@Lazy注释。
答案 1 :(得分:1)
尝试制作RestResources事务。
使用@Transactional
答案 2 :(得分:0)
添加以下依赖项
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate4</artifactId>
</dependency>
添加配置类。
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter{
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
//Registering Hibernate4Module to support lazy objects
mapper.registerModule(new Hibernate4Module());
messageConverter.setObjectMapper(mapper);
return messageConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//Here we add our custom-configured HttpMessageConverter
converters.add(jacksonMessageConverter());
super.configureMessageConverters(converters);
}
}