Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

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

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "catalog_id")
    private int catalog_id;

    @NotEmpty
    @Size(min = 3, max = 255)
    @Column(name = "name", nullable = false)
    private String name;

    @OneToMany(mappedBy="mycatalogorder")
    private List<Order> orders;

    @OneToMany(mappedBy="mycatalog")
    private List<CatalogItem> items;

    // setters and getters
}

 @Entity
 @Table(name = "catalogitem")
 public class CatalogItem {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "catalogitem_id")
    private int catalogitem_id;

    @NotEmpty
    @Size(min = 3, max = 255)
    @Column(name = "name", nullable = false)
    private String name;

    @NotEmpty
    @Column(name = "price", nullable = false)
    private Double price;

    @OneToOne(mappedBy="ordercatalogitem", cascade=CascadeType.ALL)
    private OrderItem morderitem;

    @ManyToOne
    @JoinColumn(name="catalog_id", nullable=false)
    private Catalog mycatalog;

    // setters and getters
}

@Entity
@Table(name = "orders")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "order_id")
    private int order_id;

    @NotEmpty
    @Size(min = 3, max = 255)
    @Column(name = "name", nullable = false)
    private String name;

    @NotEmpty
    @Size(min = 3, max = 1024)
    @Column(name = "note", nullable = false)
    private String note;

    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "ddmmYYYY HH:mm:ss")
    @Column(name = "created", nullable = false)
    private Date created;

    @OneToMany(mappedBy="myorder")
    private Set<OrderItem> orderItems;

    @ManyToOne
    @JoinColumn(name="catalog_id", nullable=false)
    private Catalog mycatalogorder;

    @PrePersist
    protected void onCreate() {
        created = new Date();
    }

    // setters and getters
}

@Entity
@Table(name = "orderitem")
public class OrderItem {

    @Id
    @Column(name="catalogitem_id", unique=true, nullable=false)
    @GeneratedValue(generator="gen")
    @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="catalogitem"))
    private int catalogitem_id;

    @Column(name = "quantity")
    private int quantity;

    @OneToOne
    @PrimaryKeyJoinColumn
    private CatalogItem ordercatalogitem;

    @ManyToOne
    @JoinColumn(name="order_id", nullable=false)
    private Order myorder;
     // setters and getters
}

And I am getting the exception:

org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: failed to lazily initialize a collection of role: com.example.helios.model.Catalog.items, could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.example.helios.model.Catalog.items, could not initialize proxy - no Session org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:271) org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100) org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:222) org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:183) org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80) org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)

My versions is:

  • SpringFramework 4.2.4.RELEASE
  • Hibernate 4.3.11.Final
  • Jackson 2.7.4
  • Jacksontype 2.7.1
like image 593
KostasC Avatar asked Feb 07 '17 12:02

KostasC


3 Answers

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

like image 72
Angelo Immediata Avatar answered Oct 23 '22 12:10

Angelo Immediata


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

like image 2
otonglet Avatar answered Oct 23 '22 11:10

otonglet


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/

like image 2
Cruz Ortiz Avatar answered Oct 23 '22 10:10

Cruz Ortiz