Search code examples
javajsonspringjpaentity-relationship

@OneToMany column is not present in JSON


I have the following entities:

Book.java

@Entity @Data
public class Book {

    @Id
    private Long id;

    @Column(unique = true, nullable = false)
    private String title;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "book")
    @JsonManagedReference
    private List<Note> notes;

}

Note.java

@Entity @Data
public class Note {

    @Id
    private Long id;

    @Column(nullable = false)
    private String title;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "book_id", nullable = false)
    @JsonBackReference
    private Book book;

}

When I call my BookRestController, it returns a JSON containing all the properties I need:

{
    "id": 15,
    "title": "A fé explicada",
    "author": "Leo J. Trese",
    "notes": [{
        "id": 10,
        "title": "Sobre o pecado mortal"
    }]
}

But when I call NoteRestController, the Book attribute is missing:

{
   "id": 10,
   "title": "Sobre o pecado mortal"
   // missing "book" property here...
}

What am I doing wrong?

I'm using @OneToMany and @ManyToOne annotations to declare that it's a 1-N relationship; @JsonBackReference and @JsonManagedReference have the simple purpose to avoid infinite recursion.


Solution

  • Of course Book is omitted, that is what literally @JsonBackReference is for

    @JsonBackReference is the back part of reference – it will be omitted from serialization.

    (https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion)

    The solution is as simple as it sounds: Instead of returning a Note entity in your REST controller (which I try to avoid as far as possible anyway to keep entities as entities that don't have any use in the REST context anyway) you can create a explicit transport object called e. g. NoteDTO which contains a reference to a book (that omits the notes of the book to not have infinite recursion):

    public class NoteDTO {
    
        private Long id;
        private String title;
        private BookReferenceDTO book;
    
        // getters and setters
    }
    
    public class BookReferenceDTO {
    
        private Long id;
        private String title;
    
        // getters and setters
    }