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
相关产品推荐
相关产品推荐

