1

I am developing a REST API and I have a Question parent and Answer (and User associated with both) children. What I want to achieve is that with questionService.getAllQuestions() only the questions and users are loaded from the database. When I call questionService.getQuestion(id) I want that question loaded from the database together with all the answers and the users (who answered) that question contains. All the data is automatically converted to JSON objects by Spring-boot

But in my current situation, even with getAllQuestions(), ALL the data is loaded from the database. It's pointless for the question overview request, but is necessary for the question details request.

Question parent Entity:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;

import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Set;

@Entity
@Table(name = "vragen")
public class Question extends BaseEntity {
    @Column(name = "vraag")
    private String question;

    @Column(name = "bericht")
    private String message;

    @ManyToOne
    @JoinColumn(name = "gebruiker")
    private Gebruiker gebruiker;

    @Column(name = "beantwoord", insertable = false)
    private boolean answered;

    @Column(name = "gepost_op", insertable = false)
    private Timestamp postedOn;

    @Column(name = "actief", insertable = false)
    @JsonIgnore
    private boolean active;

    @OneToMany(mappedBy = "question")
    @JsonManagedReference
    private Set<Answer> answers;


    public Question() {}

    public Question(String question, String message, Gebruiker gebruiker) {
        this.question = question;
        this.message = message;
        this.gebruiker = gebruiker;
    }

    public String getQuestion() {
        return question;
    }

    public void setQuestion(String question) {
        this.question = question;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Gebruiker getGebruiker() {
        return gebruiker;
    }

    public void setGebruiker(Gebruiker gebruiker) {
        this.gebruiker = gebruiker;
    }

    public boolean isAnswered() {
        return answered;
    }

    public void setAnswered(boolean answered) {
        this.answered = answered;
    }

    public Timestamp getPostedOn() {
        return postedOn;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public Set<Answer> getAnswers() {
        return answers;
    }

    public void setAnswers(Set<Answer> answers) {
        this.answers = answers;
    }
}

Answer Entity:

import com.fasterxml.jackson.annotation.JsonBackReference;

import javax.persistence.*;
import javax.validation.constraints.Size;
import java.sql.Timestamp;

@Entity
@Table(name = "antwoorden")
public class Answer extends BaseEntity {
    @Size(min = 10)
    @Column(name = "bericht")
    private String message;

    @ManyToOne
    @JoinColumn(name = "gebruiker")
    private Gebruiker gebruiker;

    @ManyToOne
    @JoinColumn(name = "vraag")
    @JsonBackReference
    private Question question;

    @Column(name = "gepost_op", insertable = false)
    private Timestamp postedOn;

    @Column(name = "actief", insertable = false)
    private boolean active;


    public Answer() {}

    public Answer(String message, Gebruiker gebruiker, Question question) {

    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Gebruiker getGebruiker() {
        return gebruiker;
    }

    public void setGebruiker(Gebruiker gebruiker) {
        this.gebruiker = gebruiker;
    }

    public Question getQuestion() {
        return question;
    }

    public void setQuestion(Question question) {
        this.question = question;
    }

    public Timestamp getPostedOn() {
        return postedOn;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }
}

@OneToMany is supposed to lazy load the answers by default, which doesn't happen, even if I explicitly set that option.

Is it possible to achieve this with JPA or do I need to write the queries manually in a custom implementation?

aardbol
  • 2,147
  • 3
  • 31
  • 42

1 Answers1

1

I noticed that it's Jackson that's causing it, specifically the @JsonManagedReference. Removing it and adding @JsonBackReference makes it lazy load correctly, although that annotation is not really in place here.

See Configure Jackson to omit lazy-loading attributes in Spring Boot for a real solution

aardbol
  • 2,147
  • 3
  • 31
  • 42