【问题标题】:Could not write JSON: Infinite recursion无法写入 JSON:无限递归
【发布时间】:2020-05-13 23:20:19
【问题描述】:

我在 Postman 或 Browser 中运行查询时遇到 StackOverflow 递归错误。

当我跑步时说:

.w.s.m.s.DefaultHandlerExceptionResolver:无法写入 JSON:无限递归 (StackOverflowError);嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)

这里是模型类:

@Entity 
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotNull
    private String title;
    @NotNull
    private String description;
    @NotNull
    private double price;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "category_id", nullable = false)
    private Category category;
    private boolean isSealed;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "currency_id", nullable = false)
    private Currency currency;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;
    @Nullable
    @OneToMany(mappedBy = "product",
            cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Images> images;
    private Date createdDate = new Date();
    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            mappedBy = "product")
    private View view;
    @OneToOne(fetch = FetchType.LAZY,cascade=CascadeType.ALL)
    @JoinColumn(name="type_id")
    private Type type;
    private Long viewCount; }
@Entity public class Images{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String imagePath;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id")
    private Product product; }
@Entity public class User implements UserDetails, Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotEmpty
    private String fullName;
    @NotEmpty
    @Email
    @Column(unique = true)
    private String email;
    @NotNull
    @Column(unique = true)
    private int phoneNumber;
    @NotEmpty
    @Size(min = 5)
    private String password;
    private Date createAt = new Date();
    @Nullable
    private String picPath;
    @Nullable
    private String token;
    @ManyToMany
    @JoinTable(name = "user_roles", joinColumns = {@JoinColumn(
            name = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id")})
    private List<Role> roles;
    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            mappedBy = "user")
    private Product product;
    @OneToOne(fetch = FetchType.LAZY,
    cascade = CascadeType.ALL,
    mappedBy = "user")
    private View view; }
@Entity 
public class Currency{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String code;
    private String currency;
    private String region_country;
    @OneToOne(mappedBy = "currency", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Product product; }
@Entity 
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String imagePath;
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
    mappedBy = "category")
    private Product product;
    @OneToMany(mappedBy = "category", fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    private Set<Brand> brands; }
@Entity public class Brand {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "category_id", nullable = false)
    private Category category; }
@Entity public class View {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "product_id", nullable = false)
    private Product product; }
@Entity public class Type {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotNull
    private String name;
    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            mappedBy = "type")
    private Product product; }
    @Id
    private String role;
    @ManyToMany(mappedBy = "roles")
    private List<User> users; 
}

【问题讨论】:

    标签: spring spring-mvc jpa spring-data-jpa hibernate-mapping


    【解决方案1】:

    您的多个实体本身具有彼此。 例如,Product 的对象为 UserUser 的对象为 Product

    要解决这个问题,你必须写

    @JsonBackReference(value = "user-product")
    private User user;
    

    Product 类中, 和

    @JsonManagedReference(value = "user-product")
    private Product product;
    

    user 类中。 在每个领域和每个相互调用的类中都这样做。

    另外,看看这个 JPA: Having lists on both ends without infinite loop

    【讨论】:

      【解决方案2】:

      您的数据模型中有循环。例如,Product 持有ImagesImages 指向Products

      这适用于面向对象的世界,因为只有指针引用存储在这些字段中。

      然而,当序列化时,实际对象被写为 json 文本。您的Product 打印Images 对象,该对象又打印Product 对象,该对象再次打印Image 对象,依此类推。

      您需要决定如何表示您的 json,将您的数据库模型映射到简单的普通 Java 对象,并将其用于序列化。这些 POJO 通常称为 View ModelTransport Objects

      【讨论】:

        猜你喜欢
        • 2020-02-12
        • 1970-01-01
        • 2020-07-23
        • 2012-02-20
        • 2023-03-26
        • 1970-01-01
        • 2018-10-02
        • 2021-06-16
        • 1970-01-01
        相关资源
        最近更新 更多