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

Spring Boot中对象JSON序列化循环引用问题及诉求

解决Spring Boot 3.2中Hibernate实体JSON序列化循环引用及关联字段展示问题

针对你的场景,无需创建DTO、新增字段或修改原有关联注解,通过Jackson自定义序列化器即可满足需求:

步骤1:给Book类的shop字段添加自定义序列化器

在Book类的shop字段上添加Jackson的@JsonSerialize注解,指定一个将Shop对象序列化为ID的自定义序列化器,这样无论查询Shop还是Book,序列化时都会把shop字段转为对应的ID数值,同时避免循环引用。

修改后的Book类:

@Getter
@Setter
@Entity
@Table(name = "books")
public class Book{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String description;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "shop_id")
    @JsonSerialize(using = ShopIdSerializer.class) // 新增此注解
    private Shop shop;
}

步骤2:实现自定义序列化器

创建一个序列化器类,负责将Shop对象转化为它的ID:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

public class ShopIdSerializer extends StdSerializer<Shop> {

    // 构造方法,指定序列化的类型为Shop
    public ShopIdSerializer() {
        super(Shop.class);
    }

    @Override
    public void serialize(Shop shop, JsonGenerator gen, SerializerProvider provider) throws IOException {
        // 直接写入Shop的ID
        gen.writeNumber(shop.getId());
    }
}

步骤3:优化查询避免懒加载异常

因为你的关联是LAZY加载,查询Shop时如果直接用findAll(),序列化books列表时会触发Hibernate懒加载异常。需要在Shop的Repository中添加带JOIN FETCH的查询方法,提前加载关联的books:

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface ShopRepository extends CrudRepository<Shop, Long> {

    @Query("SELECT s FROM Shop s JOIN FETCH s.books")
    List<Shop> findAllWithBooks();
}

效果验证

  • 查询店铺时,返回的JSON会符合你要求的格式:Shop包含完整Book列表,每个Book的shop字段显示为ID
  • 查询书籍时,每个Book的shop字段直接显示为对应Shop的ID
  • 完全复用原有实体类,无需创建DTO,也不会触发Hibernate字段冲突错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:28:22