Greeed
Greeed

Reputation: 3

Spring Boot bi-directional relationship between two objects @OneToMany and @ManyToOne

I am trying to find a solution creating two objects (Author and Book), which can have bi-directional relationship between them. What I mean is when I try to GET all books:

{
"id":1,
"title":"Book Name",
"author":{
    "id":1,
    "name":"Author Name",
    "books":???Here the books listed maybe???
    }
}

and after that when I try to GET all authors:

{
"id":1,
"name":"Author Name",
"books":[{
    "id":1,
    "title":"Book Name",
    "author":???Here the author listed maybe???
    }]
}

without them getting in cyclic relationship causing java.lang.StackOverflowError When listing books I would like to see at least the book author name, When listing authors I would like to see at least books ids or books titles, but always both sides linked.

What I have done so far is: Book entity:

@Entity
@Data
@Table(name = "books")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String title;
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "author_id")
    @JsonBackReference
    private Author author;
}

Author entity:

@Entity
@Data
@Table(name = "authors")
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "author", cascade = CascadeType.ALL)
    @JsonManagedReference
    private Set<Book> books = new HashSet<>();
}

Book DTO:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class BookDTO {
    private Integer id;
    private String title;
    private AuthorDTO author;
}

Author DTO:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthorDTO {
    private Integer id;
    private String name;
    private Set<BookDTO> books = new HashSet<>();
}

The BookService create book method:

@Override
public BookDTO createBook(BookDTO bookDTO){
    Book newBook = modelMapper.map(bookDTO, Book.class);
    returnBook = bookRepository.save(newBook);    
    return modelMapper.map(returnBook, BookDTO.class);
}

I've read a lot of ways with @JsonManagedReference and @JsonBackReference, @JsonIgnore, etc., but I am confused for my purpose which of these is suitable, so I do not ignore none of the sides...

Upvotes: 0

Views: 322

Answers (1)

Guilherme Stella
Guilherme Stella

Reputation: 163

You do not need @JsonManagedReference and @JsonBackReference, @JsonIgnore on your entity classes since you are not de-serializing them.

You can configure your modelMapper to avoid circular references. Take a look at this answer and modelMapper's configuration docs.

Upvotes: 0

Related Questions