Skip to content
Advertisement

JPA Hibernate many to many IllegalStateException

I’m attempting to create a many to many relationship. I have a table ‘library_branch’ and i want to join ‘BookCopies’ which contains ‘bookId’, ‘branchId’ and ‘noOfCopies’. I have an error ErrorMvcAutoConfiguration$StaticView. I’m not sure where I’m causing this infinite recursion, any help will be greatly appreciated.

2021-11-26 14:54:43.544 ERROR 22348 --- [nio-8080-exec-1] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/api/branch] and exception [Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.example.demo.branch.Branch["inventory"]->org.hibernate.collection.internal.PersistentSet[0]->com.example.demo.inventory.Inventory["branch"]->com.example.demo.branch.Branch["inventory"]

enter image description here

InventoryId.java

package com.example.demo.inventory;

...

@Data @AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class InventoryId implements Serializable {

    @Column(name = "book_id")
    private int bookId;

    @Column(name = "branch_id")
    private int branchId;

}

Inventory.java

package com.example.demo.inventory;

...

@Entity(name="Inventory")
@Table(name = "tblBookCopies")
public class Inventory {
    @EmbeddedId
    private InventoryId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("branch_id")
    private Branch branch;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("book_id")
    private Book book;

    @Column(name="no_of_copies")
    private int qty;

    public Inventory( Branch branch, Book book, int qty) {
        this.id = new InventoryId(branch.getId(),book.getId());
        this.branch = branch;
        this.book = book;
        this.qty = qty;
    }

    ...
}

Branch.java

package com.example.demo.branch;

...

@Entity(name="Branch")
@Table(name="tblLibraryBranch")
public class Branch {

    @Id
    @Column(name="id")
    private int id;
    @Column(name="name")
    private String name;
    @Column(name="address")
    private String address;
    @OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Inventory> inventory = new HashSet<>();

    ...
}

Advertisement

Answer

The problem is that your Inventory points to Branch and your Branch has a reference to Inventory. The problem is coming from Jackson, you need to explain it how to follow these references that form a circular dependency.

Option 1)

Don’t use Entities for serialization. Normally you don’t want to expose the DB entities – these should be internal objects. If you map them to some DTO representation and serialize that the problem will disappear.

Option 2)

Explain to Jackson how to follow those references – you need to look at JsonManagedReference and JsonBackReference.

In your case you need to try something like (but also check number 7 in this blogpost):

@Entity(name="Inventory")
@Table(name = "tblBookCopies")
public class Inventory {
    ... 
    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("branch_id")
    @JsonManagedReference // <-------- THIS
    private Branch branch;
    ...
}

and

@Entity(name="Branch")
@Table(name="tblLibraryBranch")
public class Branch {
    ...
    @OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, orphanRemoval = true)
    @JsonBackReference // <--------- THIS
    private Set<Inventory> inventory = new HashSet<>();
    ...
}
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement