Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fetching & Updating lazy-loaded many-many fields in Spring Data REST

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.

like image 974
JW Lim Avatar asked Jun 17 '16 18:06

JW Lim


People also ask

What do you mean by fetching?

Fetch. Fetch means to go to another place to get something or someone and return with the thing or the person.

How do you use the word fetching?

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.


2 Answers

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.

like image 197
Matthew Fontana Avatar answered Sep 27 '22 19:09

Matthew Fontana


Try making your RestResources transactional.

Annotate with @Transactional

like image 26
Mihir Gohel Avatar answered Sep 27 '22 20:09

Mihir Gohel