org.hibernate.exception.ConstraintViolationException: 无法执行 JDBC 批量更新 [由于唯一约束]
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update [Due to Unique Constraint]
错误:
org.hibernate.exception.ConstraintViolationException: 无法执行 JDBC 批量更新
java.sql.BatchUpdateException:密钥 'questionId_referenceId_referenceType'
的重复条目“24-0-es_reservation_detail”
我要保存预订object。此预订 object 包含 collection 个预订详细信息 object,每个预订详细信息 object 包含 collection 个问题答案 Objects。
主要问题是 questionAnswer 的唯一约束 table
Unqiue Constraint: question_id, reference_id, reference_type.
系统保存预订时object:系统先保存预订,然后保存预订详情collection,然后所有问题答案都为0(reference_id)。添加引用 ID 为 0 的问题时,系统抛出异常,因为违反了唯一约束。
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>
.............
.............
示例:
如果我们在预订详情中保存 collection
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)
系统什么时候执行点(5)脚本。系统会通过约束违反异常。
有什么方法可以在创建下一个插入查询之前立即在 question_answer (table) 中休眠更新 reference_id。
脚本 8 必须在第 4 个脚本后 运行
脚本 9 必须在第 5 个脚本之后 运行
很可能您没有在 QuestionAnswerDTO 实体中定义对主实体的引用,即 ReservationDetails。您应该在 QuestionAnswerDTO 中配置一个 @MAnyToOne,它具有 @JoinColumn "reference_id" 之类的东西
@ManyToOne
@JoinColumn(name="persistence_id")
private ReservationDetail reservationDetail;
然后将 reservationDetail 属性 设置为其所属的实际 ReservationDetail 对象。
然后 JPA 将知道它需要使用对 REservationDetails 的引用来填充 reference_id。否则它会将其视为任何其他字段
Hiberate cascade
选项如果您在子映射中正确映射父 Class,则使用外键插入子对象。如果您没有在子映射中映射 Parent Class 而是映射为 Integer
reference_id
,则将使用单独的更新查询更新外键:
update question_answer set reference_id = ? where question_answer_id = ?
如果无法在子映射中指定父 class 对象,则可以使用变通方法。您可以将 reference_id
设置为 null
允许(在 table 上)并且您需要在子对象中设置 referenceId=null;
。然后 Hibernate 级联将插入子对象将 null
外键,然后调用更新查询来设置 referenceId
生成的外键。
注意:null
唯一列中的值如果出现不止一次,则不会被视为重复值。
错误: org.hibernate.exception.ConstraintViolationException: 无法执行 JDBC 批量更新
java.sql.BatchUpdateException:密钥 'questionId_referenceId_referenceType'
的重复条目“24-0-es_reservation_detail”我要保存预订object。此预订 object 包含 collection 个预订详细信息 object,每个预订详细信息 object 包含 collection 个问题答案 Objects。
主要问题是 questionAnswer 的唯一约束 table
Unqiue Constraint: question_id, reference_id, reference_type.
系统保存预订时object:系统先保存预订,然后保存预订详情collection,然后所有问题答案都为0(reference_id)。添加引用 ID 为 0 的问题时,系统抛出异常,因为违反了唯一约束。
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>
.............
.............
示例:
如果我们在预订详情中保存 collection
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)
系统什么时候执行点(5)脚本。系统会通过约束违反异常。
有什么方法可以在创建下一个插入查询之前立即在 question_answer (table) 中休眠更新 reference_id。
脚本 8 必须在第 4 个脚本后 运行
脚本 9 必须在第 5 个脚本之后 运行
很可能您没有在 QuestionAnswerDTO 实体中定义对主实体的引用,即 ReservationDetails。您应该在 QuestionAnswerDTO 中配置一个 @MAnyToOne,它具有 @JoinColumn "reference_id" 之类的东西
@ManyToOne
@JoinColumn(name="persistence_id")
private ReservationDetail reservationDetail;
然后将 reservationDetail 属性 设置为其所属的实际 ReservationDetail 对象。
然后 JPA 将知道它需要使用对 REservationDetails 的引用来填充 reference_id。否则它会将其视为任何其他字段
Hiberate cascade
选项如果您在子映射中正确映射父 Class,则使用外键插入子对象。如果您没有在子映射中映射 Parent Class 而是映射为 Integer
reference_id
,则将使用单独的更新查询更新外键:
update question_answer set reference_id = ? where question_answer_id = ?
如果无法在子映射中指定父 class 对象,则可以使用变通方法。您可以将 reference_id
设置为 null
允许(在 table 上)并且您需要在子对象中设置 referenceId=null;
。然后 Hibernate 级联将插入子对象将 null
外键,然后调用更新查询来设置 referenceId
生成的外键。
注意:null
唯一列中的值如果出现不止一次,则不会被视为重复值。