PostgreSQL+Hibernate多对多关系:中间表未插入数据求助
问题原因与解决方法
核心问题分析
你的代码存在三个关键问题导致中间表无法写入数据:
1. 多对多关联的维护端未正确维护关系
在@ManyToMany关联中,mappedBy属性标记的是被维护端,真正负责维护中间表关系的是未标记mappedBy的一端(即Produit类)。当前代码仅给Commande设置了商品列表,但未将新创建的Commande添加到每个Produit的commande集合中,Hibernate只会同步维护端的关联变更,因此中间表不会生成关联数据。
2. 错误使用@SecondaryTable注解
Commande类上的@SecondaryTable(name = "produit_commande")属于误用,该注解用于将单个实体的字段拆分到多个数据库表,并非指定多对多关联的中间表。多对多的中间表需要在维护端通过@JoinTable注解配置。
3. 事务未提交
addCommande方法仅开启了事务,但未执行transaction.commit()。虽然session.save会触发临时数据刷新,但未提交的事务最终会回滚,导致关联关系无法持久化到数据库。
具体修复步骤
步骤1:修正多对多关联注解
修改Produit类的@ManyToMany注解,明确中间表配置:
@Entity @Table(name="produits") public class Produit { // ...其他属性 @ManyToMany(cascade = {CascadeType.ALL}) @JoinTable( name = "product_order", // 匹配数据库中的中间表名称 joinColumns = @JoinColumn(name = "id_produit"), // 当前实体在中间表的外键 inverseJoinColumns = @JoinColumn(name = "id_commande") // 关联实体在中间表的外键 ) private List<Commande> commande = new ArrayList<>(); // 初始化集合避免空指针 // ...getter/setter方法 }
修改Commande类,移除错误注解并简化配置:
@Entity @Table(name="commandes") // 移除错误的@SecondaryTable注解 public class Commande { // ...其他属性 @ManyToMany(mappedBy = "commande", fetch=FetchType.EAGER) // 移除不必要的targetEntity和cascade(维护端已配置cascade规则) private List<Produit> listProduit = new ArrayList<>(); // 初始化集合 // ...getter/setter方法 }
步骤2:双向维护关联关系
创建订单时,不仅要给Commande设置商品列表,还要将该订单添加到每个商品的订单集合中:
public static void addCommande(Session session, Transaction transaction,Client client, List<Produit> listProduit){ Commande newCommande = new Commande(); newCommande.setClient(client); newCommande.setListProduit(listProduit); // 维护双向关联:将当前订单添加到每个商品的commande集合 for(Produit p : listProduit){ p.getCommande().add(newCommande); } try { transaction = session.beginTransaction(); session.save(newCommande); transaction.commit(); // 提交事务 System.out.println("La commande a été ajouté avec succès"); } catch (Exception e) { if(transaction != null) transaction.rollback(); e.printStackTrace(); } finally { session.close(); } }
步骤3:修复潜在细节问题
- 所有集合属性在实体类中提前初始化(如
new ArrayList<>()),避免空指针异常。 ProduitDAO和ClientDAO的查询方法无需传入transaction参数,查询操作默认无需事务支持。
验证修复
运行主类代码后,commandes表会新增订单数据,product_order中间表将生成对应的订单ID与商品ID关联记录。
内容的提问来源于stack exchange,提问作者Yassin Hammami
相关产品推荐
相关产品推荐

