Could not write content: failed to lazily initialize a collection of role

后端 未结 9 1310
说谎
说谎 2021-02-08 02:48

I have One-To-Many relationship, here is my code

@Entity
@Table(name = \"catalog\")
public class Catalog {

    @Id
    @GeneratedValue(strategy = GenerationType         


        
相关标签:
9条回答
  • 2021-02-08 03:26

    It's caused by an infinite loop when parsing datas to JSON.

    You can solve this by using @JsonManagedReference and @JsonBackReference annotations.

    Definitions from API :

    • JsonManagedReference (https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html) :

      Annotation used to indicate that annotated property is part of two-way linkage between fields; and that its role is "parent" (or "forward") link. Value type (class) of property must have a single compatible property annotated with JsonBackReference. Linkage is handled such that the property annotated with this annotation is handled normally (serialized normally, no special handling for deserialization); it is the matching back reference that requires special handling

    • JsonBackReference: (https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html):

      Annotation used to indicate that associated property is part of two-way linkage between fields; and that its role is "child" (or "back") link. Value type of the property must be a bean: it can not be a Collection, Map, Array or enumeration. Linkage is handled such that the property annotated with this annotation is not serialized; and during deserialization, its value is set to instance that has the "managed" (forward) link.

    Example:

    Owner.java:

    @JsonManagedReference
    @OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
    Set<Car> cars;
    

    Car.java:

    @JsonBackReference
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "owner_id")
    private Owner owner;
    

    Another solution is to use @JsonIgnore which will just set null to the field.

    0 讨论(0)
  • 2021-02-08 03:27

    This is the normal Hibernate behaviour

    In one to many relations, hibernate loads the father entity (Catalog in your case) but it will load the children entities List (List items and List orders in your case) in a LAZY mode

    This means you can't access to these objects because they are just proxies and not real objects

    This is usefull in order to avoid to load the full DB when you execute a query

    You have 2 solution:

    1. Load children entities in EAGER mode (I strongly suggest to you to not do it because you can load the full DB.... but it is something related to your scenario
    2. You don't serialize in your JSON the children entities by using the com.fasterxml.jackson.annotation.JsonIgnore property

    Angelo

    0 讨论(0)
  • 2021-02-08 03:30

    I know this is an old post but this might still help someone facing a similar issue. To solve the problem, iterate through the list of items and set the lazy-loadable collection to null. Then set your mapper to include NON-NULL

     for (Catalog c : allCatalogs) {
            c.setItems(null);
        }
    
    objectMapper.setSerializationInclusion(Include.NON_NULL)
    
    0 讨论(0)
  • 2021-02-08 03:32

    I had the same problem but a fixed by:

    @OneToMany
    @JoinColumn(name = "assigned_ingredient", referencedColumnName = "ingredient_id")
    @Fetch(FetchMode.JOIN) // Changing the fetch profile you can solve the problem
    @Where(clause = "active_ind = 'Y'")
    @OrderBy(clause = "meal_id ASC")
    private List<Well> ingredients;
    

    you can have more information here: https://vladmihalcea.com/the-best-way-to-handle-the-lazyinitializationexception/

    0 讨论(0)
  • 2021-02-08 03:34

    A third option which can be useful if you don't want to use EAGER mode and load up everything is to use Hibernate::initialize and only load what you need.

    Session session = sessionFactory.openSession();
    Catalog catalog = (Catalog) session.load(Catalog.class, catalogId);
    Hibernate.initialize(shelf);
    

    More information

    0 讨论(0)
  • 2021-02-08 03:35

    I think the best solution to your problem (which also is the simplest) is to set your FetchType to LAZY and simply annotate the oneToMany collection fields using @transient. Setting FetchType to EAGER isn't a good idea most times. Best of luck.

    0 讨论(0)
提交回复
热议问题