首页 文章

org.hibernate.exception.ConstraintViolationException:无法执行JDBC批量更新[由于唯一约束]

提问于
浏览
3

错误: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update

java.sql.BatchUpdateException: Duplicate entry '24-0-es_reservation_detail' for key 'questionId_referenceId_referenceType'

我要保存预订对象 . 此预留对象包含reservaitonDetails对象的集合,每个预留详细信息对象包含questionAnswers对象的集合 .

主要问题是对questionAnswer表的唯一约束

Unqiue Constraint: question_id, reference_id, reference_type.

当系统保存预约对象时:系统首先保存预约,然后收集预订详细信息,然后用0(reference_id)查询所有问题答案 . 在添加带有0引用id的问题时,系统会抛出异常,因为违反了唯一约束 .

ReservationDetail.hbm.xml

.............
.............
<set name="questionAnswers" lazy="true" cascade="all-delete-orphan" where="reference_type = 'es_reservation_detail'">
        <key column="reference_id"/>
        <one-to-many class=".....QuestionAnswerDTO" />
    </set>
.............
.............

例:

如果我们保存预订详情的收集

1. insert into reservation......... (reservation id = 1)

2. insert into reservation_detail.......   (reservation detail id = 1)
3. insert into reservation_detail.......   (reservation detail id = 2)

4. insert into question_answer..... (referece_type='RD' referece_id=0, question_id =1) - For Reservation Detail id =  1
5. insert into question_answer..... (referece_type='RD' referece_id=0, question_id =1) - For Reservation Detail id =  1

6. update reservation_detail set reservation_id = ? where reservation_detail_id = ? (reservation_id = 1, reservation_detail_id = 1)
7. update reservation_detail set reservation_id = ? where reservation_detail_id = ? (reservation_id = 1, reservation_detail_id = 2)

8. update question_answer set reference_id = ? where question_answer_id = ? (reference_id = 1 and question_answer_id =1)
9. update question_answer set reference_id = ? where question_answer_id = ? (reference_id = 2 and question_answer_id =2)

当系统执行point(5)脚本时 . 系统将通过约束违规异常 .

Is there any way that hibernate update reference_id in question_answer (table) immediately before creating next insert query.

Script 8 must run after 4th script

Script 9 must run after 5th script

2 回答

  • 1

    如果您已在子映射中正确映射父类,则Hiberate cascade 选项会使用外键插入子对象 . 如果您没有在子映射中映射父类但是作为 Integer reference_id ,那么将使用单独的更新查询更新外键:

    update question_answer set reference_id = ? where question_answer_id = ?
    

    如果您不能在子映射中指定父类对象,则可以使用变通方法 . 您可以将 reference_id 设置为 null 允许(在表格上),您需要在子对象中设置 referenceId=null; . 然后Hibernate级联将插入子对象 null 外键,然后调用更新查询来设置生成外键的 referenceId .

    注意:如果出现多次,则唯一列中的 null 值不会被视为重复值 .

  • 1

    很可能你没有在QuestionAnswerDTO实体中定义一个返回主实体的引用,即ReservationDetails . 您应该在QuestionAnswerDTO中配置@MAnyToOne,其中@JoinColumn为“reference_id”,类似于

    @ManyToOne
     @JoinColumn(name="persistence_id")
     private ReservationDetail reservationDetail;
    

    然后将reservationDetail属性设置为它所属的实际ReservationDetail对象 .

    然后JPA将知道它需要使用对REservationDetails的引用来填充reference_id . 否则它将其视为任何其他字段

相关问题