如何通过Hibernate @ManyToOne关联在JSON响应中展示关联表数据?
解决Spring Boot+Hibernate返回JSON包含关联Sizes数据的问题
问题分析与修正步骤
当前返回JSON不包含Sizes数据,核心问题集中在实体注解配置、关联字段冗余、查询加载策略三个方面:
- JSON注解配置颠倒:
@JsonBackReference会让Jackson序列化时忽略对应字段,你错误地把它放在了Good的sizes集合上,导致关联数据被过滤。 - Size实体冗余外键:手动定义的
goodId字段和@ManyToOne关联的外键冲突,Hibernate无法正确维护关联关系,导致sizes集合无法填充。 - 查询未主动加载关联数据:Hibernate默认对关联集合用懒加载,事务结束后集合会变成不可访问的代理对象,无法被JSON序列化。
- 实体缺少Getter/Setter:Jackson序列化和Hibernate字段访问都依赖Getter/Setter,缺失会导致字段无法读取或填充。
修正后的代码
Good实体
@Entity @Table(name = "goods") @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class Good { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "Title") private String title; @Enumerated(EnumType.STRING) @Column(name = "sex") private SexType sexType; @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.DETACH, CascadeType.REFRESH, CascadeType.MERGE}) @JoinColumn(name = "ManufacturerId") @JsonManagedReference private Manufacturer manufacturer; @JsonManagedReference @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.DETACH, CascadeType.REFRESH, CascadeType.MERGE}, mappedBy = "good") private List<Size> sizes; public void addSizeToGood(Size size) { if (sizes == null) sizes = new ArrayList<>(); sizes.add(size); size.setGood(this); // 维护双向关联,确保外键正确设置 } // 补充所有字段的Getter/Setter public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public SexType getSexType() { return sexType; } public void setSexType(SexType sexType) { this.sexType = sexType; } public Manufacturer getManufacturer() { return manufacturer; } public void setManufacturer(Manufacturer manufacturer) { this.manufacturer = manufacturer; } public List<Size> getSizes() { return sizes; } public void setSizes(List<Size> sizes) { this.sizes = sizes; } }
Size实体
@Entity @Table(name = "sizes") @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class Size { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "Size") private int size; @Column(name = "Quantity") private int quantity; @JsonBackReference @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.DETACH, CascadeType.REFRESH, CascadeType.MERGE}) @JoinColumn(name = "goodid") // 对应数据库外键列名 private Good good; // 补充所有字段的Getter/Setter public int getId() { return id; } public void setId(int id) { this.id = id; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } public Good getGood() { return good; } public void setGood(Good good) { this.good = good; } }
GoodDAOImpl查询方法
@Repository public class GoodDAOImpl implements GoodDAO{ @Autowired private EntityManager entityManager; @Override @Transactional public List<Good> getAllGoods() { // 使用FETCH JOIN主动加载sizes集合,避免懒加载导致的序列化问题 String hql = "SELECT DISTINCT g FROM Good g LEFT JOIN FETCH g.sizes"; TypedQuery<Good> query = entityManager.createQuery(hql, Good.class); return query.getResultList(); } }
内容的提问来源于stack exchange,提问作者velovatik
相关产品推荐
相关产品推荐

