How do I correctly expose lazy-loaded many-many fields so that users can GET
/PATCH
/POST
/DELETE
many-many entity relationships in Spring Data REST?
For example, given a Student
entity and Teacher
entity bound by a many to many relationship, with the following POJOs:
@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...
}
The entities are given repositories:
@RepositoryRestResource(path = "teacher")
public interface TeacherRepository extends CrudRepository<Teacher, int> {}
// similar repository for student
When I send a GET
to localhost:8080/teacher, I get:
"_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...)
]
}
...
BUT, when I try a GET
to http://localhost:8080/teacher/1/students, I get a 404 Not Found, even though the teacher "Bill Billie" does have a student associated with him in the database.
Interestingly, if I change the FetchType
to FetchType.EAGER
, everything works fine and I can perform the expected GET
, PATCH
, etc. What gives? Is this a bug, perhaps, or am I screwing something up?
tl;dr Many-many relations are not correctly exposed with lazy fetching, but work fine with eager fetching. How can I get lazy fetching to work with it?
Edit: If it matters, I am using Spring 4.2.6 with Spring Boot 1.3.5, and OpenJPA 2.4.1 as my JPA provider.
Fetch. Fetch means to go to another place to get something or someone and return with the thing or the person.
How to use Fetching in a sentence. She gave him her most fetching smile and stepped out of the hallway. He stepped around her, smiling down at her in a fetching kind of way. Fear not, because this chic, effective and supremely portable BBQ is powder-coated in fetching pastel shades.
Hmm I am not sure why it isn't auto-fetching someone more experienced would have to ask that, but you can specify a manual fetch with HQL's join fetch for each query.
select x from X left join fetch x.y y
After getting this working you can override your get statement with a specifically created controller as described here: Spring Data REST: Override repository method on the controller
Only other option I think might be worth trying is adding an @Lazy annotation on your Spring-data repository.
Try making your RestResources transactional.
Annotate with @Transactional
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With