当前位置: 首页 > 知识库问答 >
问题:

无法编写JSON:未能懒洋洋地初始化一个角色集合

淳于祺
2023-03-14

我尝试用java-hibernate-spring实现一个服务器REST,它返回一个JSON。

我有一个多对多关系图。

我解释得更好,我有一个供应商,有一个配料列表,每种配料都有一个供应商列表。

我创建了这个表:

CREATE TABLE supplier_ingredient (
  supplier_id BIGINT,
  ingredient_id BIGINT
)


ALTER TABLE supplier_ingredient ADD CONSTRAINT supplier_ingredient_pkey 
PRIMARY KEY(supplier_id, ingredient_id);

ALTER TABLE supplier_ingredient ADD CONSTRAINT 
fk_supplier_ingredient_ingredient_id FOREIGN KEY (ingredient_id) 
REFERENCES ingredient(id);

ALTER TABLE supplier_ingredient ADD CONSTRAINT 
fk_supplier_ingredient_supplier_id FOREIGN KEY (supplier_id) REFERENCES 
supplier(id);

然后我有配料模型:

.....
.....
@ManyToMany(mappedBy = "ingredients")
@OrderBy("created DESC")
@BatchSize(size = 1000)
private List<Supplier> suppliers = new ArrayList<>();
....
....

然后我有供应商模型:

....
@ManyToMany
@JoinTable( name = "supplier_ingredient ", 
        joinColumns = @JoinColumn(name = "supplier_id", referencedColumnName = "id"), 
        inverseJoinColumns = @JoinColumn(name = "ingredient_id", referencedColumnName = "id"), 
        foreignKey = @ForeignKey(name = "fk_supplier_ingredient_supplier_id"))
@OrderBy("created DESC")
@Cascade(CascadeType.SAVE_UPDATE)
@BatchSize(size = 1000)
private List<Ingredient> ingredients = new ArrayList<>();
....
@RequestMapping(value = "/{supplierId:[0-9]+}", method = RequestMethod.GET)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public SupplierObject get(@PathVariable Long supplierId) {

    Supplier supplier = supplierService.get(supplierId);

    SupplierObject supplierObject = new SupplierObject (supplier);

    return SupplierObject;

}

服务

....
public Supplier get(Long supplierId) {

    Supplier supplier = supplierDao.getById(supplierId); (it does entityManager.find(entityClass, id))

    if (supplier == null) throw new ResourceNotFound("supplier", supplierId);

    return supplier;
}
....

供应对象

    @JsonIgnoreProperties(ignoreUnknown = true)
    public class SupplierObject extends IdAbstractObject {

    public String email;

    public String phoneNumber;

    public String address;

    public String responsible;

    public String companyName;

    public String vat;

    public List<Ingredient> ingredients = new ArrayList<>();

    public SupplierObject () {

    }

    public SupplierObject (Supplier supplier) {

        id = supplier.getId();
        email = supplier.getEmail();
        responsible = supplier.getResponsible();
        companyName = supplier.getCompanyName();
        phoneNumber = supplier.getPhone_number();
        ingredients = supplier.getIngredients();
        vat = supplier.getVat();
        address = supplier.getAddress();


    }
}

和IdAbstractObject

public abstract class IdAbstractObject{

    public Long id;

}
http://localhost:8080/supplier/1

“无法写入JSON:未能懒洋洋地初始化Role:myPackage.Comprigue.Comprigue.Comprigue.Providers的集合,无法初始化代理-没有会话;嵌套异常是com.fasterxml.jackson.databind.jsonMappingException:未能懒洋洋地初始化Role:myPackage.Comprigue.Comprigue.Comprigue.Comprigue.Suppliers的集合,无法初始化代理-没有会话(通过引用链:myPackage.SupplierObject[\'配料\”]

我跟着说:

避免对未提取的惰性对象进行Jackson序列化

现在我没有这个错误,但是在返回的json中,成分字段是空的:

{
  "id": 1,
  "email": "mail@gmail.com",
  "phoneNumber": null,
  "address": null,
  "responsible": null,
  "companyName": "Company name",
  "vat": "vat number",
  "ingredients": null
}

但在调试中,我可以看到成分....

共有1个答案

胡劲
2023-03-14

这是Hibernate和Jackson Marshaller的正常行为基本上您需要以下内容:一个包含所有供应商对象细节的JSON...包括配料。

请注意,在这种情况下,您必须非常小心,因为当您试图创建JSON本身时,您可以有一个循环引用,所以您还应该使用JSONIgnore注释

你必须做的第一件事是装载供应商及其所有细节(成分包括在内)。

你怎么能做到?通过使用几种策略...让我们使用hibernate.initialize。这必须在DAO(或存储库)实现中的hibernate会话关闭之前使用(基本上是在使用hibernate会话的地方)。

因此,在本例中(我假设使用Hibernate),在我的存储库类中,我应该编写如下内容:

public Supplier findByKey(Long id)
{
    Supplier result = (Supplier) getSession().find(Supplier.class, id);
    Hibernate.initialize(result.getIngredients());
    return result;
}
@RequestMapping(value = "/{supplierId:[0-9]+}", method = RequestMethod.GET)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public SupplierObject get(@PathVariable Long supplierId) 
{
    Supplier supplier = supplierService.get(supplierId);
    SupplierObject supplierObject = new SupplierObject (supplier);
    return SupplierObject;
}
@ManyToMany(mappedBy = "ingredients")
@OrderBy("created DESC")
@BatchSize(size = 1000)
private List<Supplier> suppliers = new ArrayList<>();
@JsonIgnoreProperties(value= {"suppliers"})
public class Ingredient implements Serializable
{
......
}
  • 用所有相关成分加载供应商对象
  • 在尝试创建JSON本身时避免循环引用

无论如何,我建议您创建特定的DTO(或VO)对象,用于对JSON进行编组和解编组

我希望这是有用的

安杰洛

 类似资料: