OneToMany关联且带@Column(unique=true)约束时多表插入方案咨询
问题根因
你当前直接新建Makes对象并执行persist操作,没有提前校验数据库中是否已存在相同make值的记录,而MAKES表的make字段配置了唯一约束,重复插入相同值就会触发唯一键冲突异常。此外你当前代码没有维护MODELS和MAKES的@ManyToOne关联关系,不符合关联表的插入规范。
正确操作步骤
- 插入前先根据
make字段查询MAKES表:- 若已存在对应记录,直接复用查询到的持久化实例,无需重复持久化
- 若不存在对应记录,新建
Makes对象后执行persist操作
- 给
Models实例设置关联的Makes对象,维护两者的关联关系 - 同逻辑校验
MODELS表是否存在对应model值的记录,避免重复插入触发唯一键冲突,校验完成后持久化Models实例
代码示例
// 处理品牌(MAKES)逻辑 String targetMake = "Porsche"; TypedQuery<Makes> makeQuery = em.createQuery("SELECT m FROM Makes m WHERE m.make = :make", Makes.class); makeQuery.setParameter("make", targetMake); Makes makes; try { makes = makeQuery.getSingleResult(); } catch (NoResultException e) { makes = new Makes(); makes.setMake(targetMake); em.persist(makes); } // 处理车型(MODELS)逻辑 String targetModel = "911"; TypedQuery<Models> modelQuery = em.createQuery("SELECT m FROM Models m WHERE m.model = :model", Models.class); modelQuery.setParameter("model", targetModel); Models models; try { models = modelQuery.getSingleResult(); } catch (NoResultException e) { models = new Models(); models.setModel(targetModel); // 维护多对一关联关系 models.setMake(makes); em.persist(models); }
注意事项
- 整个操作需要放在同一个事务中执行,避免并发场景下查询和插入中间有其他请求插入相同数据触发冲突
- 高并发场景下可以在捕获到唯一键冲突异常后新增重试逻辑,提升操作成功率
内容的提问来源于stack exchange,提问作者Nikolay Grigoryev
相关产品推荐
相关产品推荐

