it-roy-ru.com

Не удалось записать содержимое: не удалось лениво инициализировать коллекцию ролей

У меня отношения один-ко-многим, вот мой код

@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", [email protected](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
}

И я получаю исключение:

org.springframework.http.converter.HttpMessageNotWritableException: Не удалось записать содержимое: не удалось лениво инициализировать коллекцию роль: com.example.helios.model.Catalog.items, не удалось инициализировать прокси - нет сеанса; Вложенное исключение com.fasterxml.jackson.databind.JsonMappingException: не удалось лениво инициализировать коллекцию ролей: com.example.helios.model.Catalog.items, не удалось инициализировать прокси - нет сеанса 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)

Мои версии это: 

  • SpringFramework 4.2.4.RELEASE
  • Hibernate 4.3.11.Final
  • Джексон 2.7.4
  • Джексон тип 2.7.1
4
KostasC

Это нормальное поведение Hibernate

В отношениях один ко многим hibernate загружает родительский объект (каталог в вашем случае), но загружает дочерние объекты Список (элементы списка и порядки списка в вашем случае) в режиме LAZY.

Это означает, что вы не можете получить доступ к этим объектам, потому что они просто прокси, а не реальные объекты

Это полезно во избежание загрузки полной БД при выполнении запроса

У вас есть 2 решения:

  1. Загружать дочерние объекты в режиме EAGER (я настоятельно рекомендую вам не делать этого, потому что вы можете загрузить полную БД .... но это связано с вашим сценарием
  2. Вы не сериализуете в своем JSON дочерние объекты, используя свойство com.fasterxml.jackson.annotation.JsonIgnore

Angelo

17
Angelo Immediata

Третий вариант, который может быть полезен, если вы не хотите использовать режим EAGER и загружать все, - это использовать Hibernate :: initialize и загружать только то, что вам нужно.

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

Дополнительная информация

2
otonglet

У меня была та же проблема, но исправлена:

@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;

вы можете получить больше информации здесь: https://vladmihalcea.com/the-best-way-to-handle-the-lazyinitializationexception/

1
Cruz Ortiz

При использовании FetchType.LAZY, если по-прежнему появляется ошибка «Не удалось записать содержимое: не удалось лениво инициализировать коллекцию ролей», что может быть вызвано где-то в логике (возможно, в контроллере), каталог пытается десериализовать он содержит список элементов каталога, который является прокси, но транзакция уже завершена, чтобы получить это. Итак, создайте новую модель ('CatalogResource', похожую на каталог, но без списка элементов) . Затем создайте объект catalogResource из каталога (который возвращается из запроса). 

public class CatalogResource {
    private int catalog_id;
    private String name;
    private List<Order> orders;
} 

0
mykey

Я думаю, что лучшее решение вашей проблемы (которая также является самой простой) - установить FetchType в LAZY и просто аннотировать поля коллекции oneToMany с помощью @transient . Установка FetchType в EAGER в большинстве случаев не является хорошей идеей .Удачи.

0
Christian Nwafor