I want to store some data into database through One to Many and Many to One Bidirectional relationship mapping
but while request for persist data post insert 7460
line. I can googling but not found proper solution.
Here down is my code:
Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer author_id;
private String name;
private String language;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "author")
private Set<Book> book;
// getter setter
}
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id")
private Author author;
// getter setter
}
Service
@Override
public Author insertAuthor(Author author) {
Set<Book> bookList = new HashSet<>();
Book book = new Book();
book.setTitle(book.getTitle());
bookList.add(book);
book.setAuthor(author);
author.setBook(bookList);
return authorRepo.save(author);
}
Controller
@RestController
public class PojoController {
@Autowired
private PojoService pojoService;
@RequestMapping(value="/book", method = RequestMethod.POST)
public Author addBookCourse(@RequestBody Author author) {
return this.pojoService.insertAuthor(author);
}
}
Request
{
"language": "english",
"name": "Banjamin franklin",
"book": [{
"title": "Theory Of Everything"
},
{
"title": "A Brief Story Of Time"
}]
}
Output
{
"author_id": 1,
"name": "Banjamin franklin",
"language": "english",
"book": [
{
"id": 1,
"title": null,
"author": {
"author_id": 1,
"name": "Banjamin franklin",
"language": "english",
"book": [
{
"id": 1,
"title": null,
"author": {
"author_id": 1,
"name": "Banjamin franklin",
"language": "english",
"book": [
{
"id": 1,
"title": null,
"author": {
"author_id": 1,
"name": "Banjamin franklin",
"language": "english",
"book": [
{
"id": 1,
"title": null,
more 7460 line
.......
.......
.......
{
"timestamp": "2021-11-30T10:25:03.957 00:00",
"status": 200,
"error": "OK",
"trace": "org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.rest.RestApiPojo.Entity.Author[\"book\"]->org.hibernate.collection.internal.PersistentSet[0]->com.rest.RestApiPojo.Entity.Book[\"author\"]->com.rest.RestApiPojo.Entity.Author[\"book\"]->org.hibernate.collection.internal.PersistentSet[0]->com.rest.RestApiPojo.Entity.Book[\"author\"]
}
CodePudding user response:
You need to use @JsonManagedReference
and @JsonBackReference
to allow Jackson to better handle the relationship between Author
and Book
:
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer author_id;
private String name;
private String language;
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, mappedBy = "author")
private Set<Book> book;
// getter setter
}
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id")
private Author author;
// getter setter
}
You have other options (e.g. using @JsonIdentityInfo
) to handle this infinite recursion issue, but this is the most common solution. You can check all other possible approaches at the following online resource https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion.
Additionally, in your Service you are creating a brand new Book
and setting its title with book.setTitle(book.getTitle());
, which basically does nothing. In fact you don't even need to do most of the stuff you are doing there because Book
instances are already in Author
, you just need to set Author
on each Book
instance as follows:
@Override
public Author insertAuthor(Author author) {
for (Book book : author.getBook()) {
book.setAuthor(author);
}
return authorRepo.save(author);
}
Finally, consider changing the book
property in Author
to books
since it contains multiple books (you will need to adjust your code afterwards).