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

如何通过Hibernate @ManyToOne关联在JSON响应中展示关联表数据?

解决Spring Boot+Hibernate返回JSON包含关联Sizes数据的问题

问题分析与修正步骤

当前返回JSON不包含Sizes数据,核心问题集中在实体注解配置、关联字段冗余、查询加载策略三个方面:

  1. JSON注解配置颠倒:@JsonBackReference会让Jackson序列化时忽略对应字段,你错误地把它放在了Good的sizes集合上,导致关联数据被过滤。
  2. Size实体冗余外键:手动定义的goodId字段和@ManyToOne关联的外键冲突,Hibernate无法正确维护关联关系,导致sizes集合无法填充。
  3. 查询未主动加载关联数据:Hibernate默认对关联集合用懒加载,事务结束后集合会变成不可访问的代理对象,无法被JSON序列化。
  4. 实体缺少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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 13:05:07