Json 无法写入内容:未能延迟初始化角色的集合

Json 无法写入内容:未能延迟初始化角色的集合,json,spring,hibernate,jackson,Json,Spring,Hibernate,Jackson,我有一对多的关系,这是我的代码 @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

我有一对多的关系,这是我的代码

@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
}
@实体
@表(name=“catalog”)
公共类目录{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“catalog\u id”)
私有int目录id;
@空空如也
@尺寸(最小值=3,最大值=255)
@列(name=“name”,nullable=false)
私有字符串名称;
@OneToMany(mappedBy=“mycatalogorder”)
私人名单订单;
@OneToMany(mappedBy=“mycatalog”)
私人清单项目;
//二传手和接球手
}
@实体
@表(name=“catalogitem”)
公共类目录项{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“catalogitem\u id”)
私有int catalogitem_id;
@空空如也
@尺寸(最小值=3,最大值=255)
@列(name=“name”,nullable=false)
私有字符串名称;
@空空如也
@列(name=“price”,nullable=false)
私人双价;
@OneTONE(mappedBy=“ordercatalogitem”,cascade=CascadeType.ALL)
私人订单项目;
@许多酮
@JoinColumn(name=“catalog\u id”,nullable=false)
私人目录mycatalog;
//二传手和接球手
}
@实体
@表(name=“orders”)
公共阶级秩序{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“order\u id”)
私人内部订单号;
@空空如也
@尺寸(最小值=3,最大值=255)
@列(name=“name”,nullable=false)
私有字符串名称;
@空空如也
@尺寸(最小值=3,最大值=1024)
@列(name=“note”,nullable=false)
私人弦乐;
@时态(TemporalType.TIMESTAMP)
@DateTimeFormat(pattern=“ddmmYYYY HH:mm:ss”)
@列(name=“created”,nullable=false)
创建私人日期;
@OneToMany(mappedBy=“myorder”)
私人设置订单项;
@许多酮
@JoinColumn(name=“catalog\u id”,nullable=false)
私人目录mycatalogorder;
@预科生
受保护的void onCreate(){
已创建=新日期();
}
//二传手和接球手
}
@实体
@表(name=“orderitem”)
公共类OrderItem{
@身份证
@列(name=“catalogitem\u id”,unique=true,nullable=false)
@生成值(generator=“gen”)
@GenericGenerator(name=“gen”,strategy=“foreign”,parameters=@Parameter(name=“property”,value=“catalogitem”))
私有int catalogitem_id;
@列(名称=“数量”)
私人整数数量;
@奥内托内
@PrimaryKeyJoinColumn
私有目录项ordercatalogitem;
@许多酮
@JoinColumn(name=“order\u id”,null=false)
私人订单;
//二传手和接球手
}
我得到了一个例外:

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.WriteWithMessageConverterMethodProcessor(AbstractMessageConverterMethodProcessor.java:222) org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:183) org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.HandlerReturnValue(HandlerMethodReturnValueHandlerComposite.java:80) org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)

我的版本是:

  • SpringFramework 4.2.4.1版本
  • Hibernate 4.3.11.1最终版本
  • 杰克逊2.7.4
  • Jacksontype 2.7.1

    • 这是正常的休眠行为

      在一对多关系中,hibernate加载父实体(本例中为目录),但它将以延迟模式加载子实体列表(本例中为列表项和列表顺序)

      这意味着您无法访问这些对象,因为它们只是代理而不是真实对象

      这非常有用,以避免在执行查询时加载完整的数据库

      您有两个解决方案:

    • 在急切模式下加载子实体(我强烈建议您不要这样做,因为您可以加载完整的DB…,但这与您的场景有关
    • 您不会使用com.fasterxml.jackson.annotation.JsonIgnore属性在JSON中序列化子实体

    • Angelo

      如果您不想使用渴望模式并加载所有内容,那么第三个选项很有用,就是使用Hibernate::initialize并只加载您需要的内容

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

      使用FetchType.LAZY,如果仍然出现错误“无法写入内容:无法延迟初始化角色集合”,这可能是由于逻辑中的某个地方(可能是控制器中)导致的,正在尝试反序列化包含作为代理的目录项列表的目录,但事务已结束以获取该目录项。 因此,创建一个新模型(“CatalogResource”类似于catalog,但不包含项目列表)。 然后从目录中创建catalogResource对象(从查询返回)

      公共类目录资源{
      私有int目录id;
      私有字符串名称;
      私人名单订单;
      
      }
      我认为解决问题的最佳方法(也是最简单的方法)是将FetchType设置为LAZY,并使用@transient简单地注释oneToMany集合字段。 大多数情况下,将FetchType设置为EAGER不是一个好主意。 B
      @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;
      
      @JsonManagedReference
      @OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
      Set<Car> cars;
      
      @JsonBackReference
      @ManyToOne(fetch = FetchType.EAGER)
      @JoinColumn(name = "owner_id")
      private Owner owner;
      
      @JsonIgnore
      @OneToMany(mappedBy = "myorder")
      private List<OrderItem> orderItems = new ArrayList<>();
      
      @JsonProperty(value = "order_items", access = JsonProperty.Access.READ_ONLY)
      private List<OrderItem> getOrderItemsList() {
      
          if(Hibernate.isInitialized(this.relatedDictionary)){
              return this.relatedDictionary;
          } else{
              return new ArrayList<>();
          }
      }
      
      @JsonProperty(value = "order_items", access = JsonProperty.Access.WRITE_ONLY)
      private void setOrderItemsList(List<OrderItem> orderItems) {
          this.orderItems = orderItems;
      }
      
       for (Catalog c : allCatalogs) {
              c.setItems(null);
          }
      
      objectMapper.setSerializationInclusion(Include.NON_NULL)