You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决添加JPA关联后出现的com.fasterxml.jackson.databind.ser错误

JPA实体关联引发Jackson Databind序列化错误

问题背景

配置JPA实体间的ManyToOne和OneToMany关联后,出现Jackson Databind序列化错误,怀疑是关联配置导致的问题。Product实体对应Northwind数据库的产品表,关联了Category和Supplier表。

错误信息

at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]

关联后的实体代码

Product实体

package com.JpaTraining.JpaTraining.entities.concretes;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import lombok.Data;

@Entity
@Data
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "product_id")
    private int productId;
    @Column(name = "product_name")
    private String productName;

    @ManyToOne
    @JoinColumn(name = "supplier_id")
    private Supplier supplier;

    @ManyToOne
    @JoinColumn(name = "category_id")
    private Category category;
    @Column(name = "unit_price")
    private double unitPrice;
    @Column(name = "units_in_stock")
    private int unitsInStock;

    public Product() {
    }

    public Product(int productId, String productName, Supplier supplier, Category category, double unitPrice,
            int unitsInStock) {
        this.productId = productId;
        this.productName = productName;
        this.supplier = supplier;
        this.category = category;
        this.unitPrice = unitPrice;
        this.unitsInStock = unitsInStock;
    }
}

Category实体

package com.JpaTraining.JpaTraining.entities.concretes;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import lombok.Data;

@Entity
@Data
@Table(name = "categories")
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "category_id")
    private int categoryId;
    @Column(name = "category_name")
    private String categoryName;

    @OneToMany(mappedBy = "category")
    private List<Product> product;

    public Category() {
    }

    public Category(int categoryId, String categoryName, List<Product> product) {
        this.categoryId = categoryId;
        this.categoryName = categoryName;
        this.product = product;
    }
}

Supplier实体

package com.JpaTraining.JpaTraining.entities.concretes;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import lombok.Data;

@Entity
@Data
@Table(name = "suppliers")
public class Supplier {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "supplier_id")
    private int supplierId;
    @Column(name = "company_name")
    private String supplierName;

    @OneToMany(mappedBy = "supplier")
    private List<Product> product;

    public Supplier() {

    }

    public Supplier(int supplierId, String supplierName, List<Product> product) {
        this.supplierId = supplierId;
        this.supplierName = supplierName;
        this.product = product;
    }

}

数据库字符集配置

产品表字符集
供应商表字符集
分类表字符集


解决方案

这个错误的核心原因是实体间的双向关联导致Jackson序列化时出现循环引用:Product引用了Category/Supplier,而Category/Supplier又反过来引用了Product列表,序列化时会无限递归调用,最终抛出异常。

解决方法(按需选择):

  1. 添加@JsonIgnore注解:在双向关联的一方忽略序列化,比如在Category和Supplier的product字段上添加:
@OneToMany(mappedBy = "category")
@JsonIgnore
private List<Product> product;
  1. 使用@JsonManagedReference和@JsonBackReference:区分双向关联的主动/被动方,避免循环:
  • 在Product的supplier和category字段上添加@JsonManagedReference
  • 在Category和Supplier的product字段上添加@JsonBackReference
  1. 使用DTO传输数据:创建专门的DTO类,只包含需要返回的字段,序列化时转换为DTO而非直接序列化实体类,彻底隔离实体关联与前端数据结构。

另外,建议将实体类中List<Product>的变量名改为products(复数形式),符合编码规范,避免歧义。


内容的提问来源于stack exchange,提问作者Emre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:01:45