org.hibernate.exception.ConstraintViolationException:无法执行 JDBC 批量更新

Posted

技术标签:

【中文标题】org.hibernate.exception.ConstraintViolationException:无法执行 JDBC 批量更新【英文标题】:org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 【发布时间】:2011-04-28 18:41:06 【问题描述】:

在我正在处理的模块中,我收到了这个错误,据说是由org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 引起的 和java.sql.BatchUpdateException(完整的堆栈跟踪在这里:click here)。

从我从其他帖子中读到的内容来看,这肯定是由于违反了主键造成的。但是我什至无法复制问题,以便我至少可以追踪真正的错误并解决问题。每次我插入一个与数据库中已经存在的条目相同的条目时,它都会简单地相互合并而不会出错。但是,我在部署中遇到了很多这样的错误,所以我不太确定部署服务器中发生了什么(我只是一名学生开发人员,所以在这方面我还是有点“菜鸟”)。

即使有人能指出我的方向,我也会很感激。谢谢。 (有什么需要补充的告诉我)

这是模块的休眠映射的 sn-p(希望这会有所帮助):

<hibernate-mapping package="edu.umd.cattlab.schema.cattXML.extensions.VaTraffic"
default-lazy="false" default-cascade="all, delete-orphan" schema="vatraffic">

<typedef class="edu.umd.cattlab.schema.hibernate.util.XMLGregorianCalendarType" name="XMLCal"/>

<class name="VaTrafficAssociatedEvent" table="associated_event">
    <id name="associatedEventId" column="associated_event_id">
        <generator class="sequence">
            <param name="sequence">ritis.associated_event_id_seq</param>
        </generator>
    </id>

    <property name="secondaryEventId" column="secondary_event_id" not-null="true" />
    <property name="unassociatedTimestamp" type="XMLCal" column="unassociated" />
    <property name="autoRelated" column="auto_related" not-null="true" />
    <many-to-one name="relationshipType" column="relationship_type" not-null="true" cascade="none" />
 </class>

这是利用上述映射的java代码部分:click here

【问题讨论】:

您发布的 Dropbox 链接导致 403 错误。 对不起,我的错。我更新了链接。 你用什么方法保存?你的主键是如何映射到 XML 或注解中的? (这个模块实际上是由其他开发人员编写的,但是)该模块使用合并技术将对象保存到数据库。所以它应该插入一个新对象或在它已经存在时合并它。对于映射,我已经把它放在了这个问题的最新编辑中。 【参考方案1】:

你可以有更多的约束,而不仅仅是一个主键约束。可能是您违反了外键约束吗?或者可能是多列唯一约束。能否请您包含正在更新的表的 DDL?

【讨论】:

这里是表格的 ddl:link 对不起,这是正确的链接:link【参考方案2】:

在查看日志时,它违反了 pk 约束。特别是错误:重复键违反唯一约束“关联事件pk”

试图确定为什么会发生这种情况可能需要深入研究,但对于初学者来说,您是如何为该字段生成值的?在您的 ddl 中,它显示为“nextval”字段,但您的日志似乎表明存在显式值。这个值是从哪里来的?为什么不让 postgre 自己设置值?

【讨论】:

感谢您的洞察力,但您能对此进行更多解释吗?不太明白 堆栈跟踪是由您的 associated_event_pk 主键约束引起的。就像您通过尝试向已经存在的表中添加第二个主键来破坏主键一样。您如何生成主键?您是允许数据库为您提供主键还是您自己生成它们?您是否尝试更新对象,但不是调用 saveorupdate 而是在休眠会话上调用 save 吗? 所以主键是由序列“ritis.associated_event_id_seq”生成的。每次将新的关联事件插入数据库时​​都会生成它。但是,如果事件已经存在,它只会更新关联的事件。有什么问题吗? 所以在查看您的日志时,您似乎正在尝试显式设置 ID。它是否正确?如果是这样,您为什么要这样做而不让数据库确定值本身?在应用程序中执行此操作可能会导致在大量场景中出现奇怪的行为。 DB 已经非常可靠地解决了这个问题,让他们处理它,而不是重新发明***。 哼哼,其实模块并没有明确的确定id,实际上id的key都是由数据库管理的(从hibernate映射中可以看出)。您在日志中看到的内容可能来自 log4j 日志记录,该日志记录显示任何在发生时会导致错误的查询。它与模块处理主 id 的方式无关。

以上是关于org.hibernate.exception.ConstraintViolationException:无法执行 JDBC 批量更新的主要内容,如果未能解决你的问题,请参考以下文章