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

发布于 09-16 13:53 字数 6095 浏览 10 评论 0原文

尽管数据已成功插入,但我得到了下面提到的堆栈跟踪。

Hibernate: select attendee_.attendeeId, attendee_.attendeeName as attendee2_1_ from attendee attendee_ where attendee_.attendeeId=?
Hibernate: select attendee_.attendeeId, attendee_.attendeeName as attendee2_1_ from attendee attendee_ where attendee_.attendeeId=?
Hibernate: insert into event (eventName, startDate, eventId) values (?, ?, ?)
Hibernate: insert into attendee (attendeeName, attendeeId) values (?, ?)
Hibernate: insert into attendee (attendeeName, attendeeId) values (?, ?)
Hibernate: update attendee set attendeeId=? where attendeeId=?
Hibernate: update attendee set attendeeId=? where attendeeId=?
Aug 29, 2010 7:39:10 PM org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 1062, SQLState: 23000
Aug 29, 2010 7:39:10 PM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: Duplicate entry '11' for key 'PRIMARY'
Aug 29, 2010 7:39:10 PM org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980)
    at com.practice.hibernate.basic.BasicOperations.main(BasicOperations.java:51)
Caused by: java.sql.BatchUpdateException: Duplicate entry '11' for key 'PRIMARY'
    at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:665)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
    ... 6 more
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980)
    at com.practice.hibernate.basic.BasicOperations.main(BasicOperations.java:51)
Caused by: java.sql.BatchUpdateException: Duplicate entry '11' for key 'PRIMARY'
    at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:665)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
    ... 6 more

请注意:

a) 我的数据库当前没有记录 b) 数据成功插入数据库。

在这里,我尝试保留一个包含两个参加者对象的事件对象。仅此而已。

我的测试类:

public static void main(String[] args) {
    Session session = HibernateRuntime.getSession();

    try {
        Set<Attendee> attendees = new HashSet<Attendee>(2);

        Attendee attendee = new Attendee();
        attendee.setAttendeeId(3);
        attendee.setAttendeeName("Baswanth Rao");

        Attendee attendee1 = new Attendee();
        attendee1.setAttendeeId(4);
        attendee1.setAttendeeName("Razi Ahmed");

        attendees.add(attendee);
        attendees.add(attendee1);

        Event event = new Event();
        event.setEventId(11);
        event.setEventName("Initiatives Workshop 3");
        event.setStartDate(new Date());
        event.setAttendees(attendees);

        session.save(event);
        session.flush();

    } finally {
        session.close();
    }
}

Event.hbm.xml:

<hibernate-mapping package="com.practice.hibernate.vo">
    <class name="Event" table="event">
        <id name="eventId" column="eventId" type="long">
            <generator class="assigned" />
        </id>

        <property name="eventName" type="string" length="100" />
        <property name="startDate" type="date" />

        <set name="attendees" cascade="all">
            <key column="attendeeId" />
            <one-to-many class="Attendee" />
        </set>
    </class>
</hibernate-mapping>

hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/test</property>
        <property name="connection.username">root</property>
        <property name="connection.password"></property>
        <property name="connection.autocommit">false</property>

        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>

        <mapping resource="com/practice/hibernate/vo/Event.hbm.xml"></mapping>
        <mapping resource="com/practice/hibernate/vo/Attendee.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>

I get below mentioned stack trace though the data gets inserted successfully.

Hibernate: select attendee_.attendeeId, attendee_.attendeeName as attendee2_1_ from attendee attendee_ where attendee_.attendeeId=?
Hibernate: select attendee_.attendeeId, attendee_.attendeeName as attendee2_1_ from attendee attendee_ where attendee_.attendeeId=?
Hibernate: insert into event (eventName, startDate, eventId) values (?, ?, ?)
Hibernate: insert into attendee (attendeeName, attendeeId) values (?, ?)
Hibernate: insert into attendee (attendeeName, attendeeId) values (?, ?)
Hibernate: update attendee set attendeeId=? where attendeeId=?
Hibernate: update attendee set attendeeId=? where attendeeId=?
Aug 29, 2010 7:39:10 PM org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 1062, SQLState: 23000
Aug 29, 2010 7:39:10 PM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: Duplicate entry '11' for key 'PRIMARY'
Aug 29, 2010 7:39:10 PM org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980)
    at com.practice.hibernate.basic.BasicOperations.main(BasicOperations.java:51)
Caused by: java.sql.BatchUpdateException: Duplicate entry '11' for key 'PRIMARY'
    at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:665)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
    ... 6 more
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980)
    at com.practice.hibernate.basic.BasicOperations.main(BasicOperations.java:51)
Caused by: java.sql.BatchUpdateException: Duplicate entry '11' for key 'PRIMARY'
    at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:665)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
    ... 6 more

Please note:

a) My db has no records currently
b) Data gets inserted into DB successfully.

Here I am trying to persist an Event object which contains two Attendee Objects. That is all.

My Test Class:

public static void main(String[] args) {
    Session session = HibernateRuntime.getSession();

    try {
        Set<Attendee> attendees = new HashSet<Attendee>(2);

        Attendee attendee = new Attendee();
        attendee.setAttendeeId(3);
        attendee.setAttendeeName("Baswanth Rao");

        Attendee attendee1 = new Attendee();
        attendee1.setAttendeeId(4);
        attendee1.setAttendeeName("Razi Ahmed");

        attendees.add(attendee);
        attendees.add(attendee1);

        Event event = new Event();
        event.setEventId(11);
        event.setEventName("Initiatives Workshop 3");
        event.setStartDate(new Date());
        event.setAttendees(attendees);

        session.save(event);
        session.flush();

    } finally {
        session.close();
    }
}

Event.hbm.xml:

<hibernate-mapping package="com.practice.hibernate.vo">
    <class name="Event" table="event">
        <id name="eventId" column="eventId" type="long">
            <generator class="assigned" />
        </id>

        <property name="eventName" type="string" length="100" />
        <property name="startDate" type="date" />

        <set name="attendees" cascade="all">
            <key column="attendeeId" />
            <one-to-many class="Attendee" />
        </set>
    </class>
</hibernate-mapping>

hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/test</property>
        <property name="connection.username">root</property>
        <property name="connection.password"></property>
        <property name="connection.autocommit">false</property>

        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>

        <mapping resource="com/practice/hibernate/vo/Event.hbm.xml"></mapping>
        <mapping resource="com/practice/hibernate/vo/Attendee.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

野生奥特曼2024-09-23 13:53:14

您的 Event.hbm.xml 表示:

<set name="attendees" cascade="all">
    <key column="attendeeId" />
    <one-to-many class="Attendee" />
</set>

用简单的英语来说,这意味着 Attendee.attendeeId 列是关联 attendees外键,并且指向Event的主键。

当您将这些参加者添加到事件中时,hibernate 会更新外键以表达更改后的关联。由于同一列也是参加者的主键,因此这违反了主键约束。

由于参加者的身份和活动参与是独立的,因此您应该对主键和外键使用单独的列。

编辑:选择可能是因为您似乎没有配置版本属性,使得休眠无法知道与会者是否已存在于数据库中(它们可能已在上一个会话中加载),因此休眠会发出选择检查。至于更新语句,这种方式可能更容易实现。如果您想摆脱这些单独的更新,我建议从两端映射关联,并将 Event-end 声明为 inverse

Your Event.hbm.xml says:

<set name="attendees" cascade="all">
    <key column="attendeeId" />
    <one-to-many class="Attendee" />
</set>

In plain english, this means that the column Attendee.attendeeId is the foreign key for the association attendees and points to the primary key of Event.

When you add those Attendees to the event, hibernate updates the foreign key to express the changed association. Since that same column is also the primary key of Attendee, this violates the primary key constraint.

Since an Attendee's identity and event participation are independent, you should use separate columns for the primary and foreign key.

Edit: The selects might be because you don't appear to have a version property configured, making it impossible for hibernate to know whether the attendees already exists in the database (they might have been loaded in a previous session), so hibernate emits selects to check. As for the update statements, it was probably easier to implement that way. If you want to get rid of these separate updates, I recommend mapping the association from both ends, and declare the Event-end as inverse.

Smile简单爱2024-09-23 13:53:14

您可以在这里找到完整的示例代码:
http://www.java2s.com/Code/Java/Hibernate/OneToManyMappingbasedonSet。 htm

看一下并检查差异。特别是中的 Even_id :

<set name="attendees" cascade="all">
    <key column="event_id"/>
    <one-to-many class="Attendee"/>
</set> 

You can find your sample code completely here:
http://www.java2s.com/Code/Java/Hibernate/OneToManyMappingbasedonSet.htm

Have a look and check the differences. specially the even_id in :

<set name="attendees" cascade="all">
    <key column="event_id"/>
    <one-to-many class="Attendee"/>
</set> 
情深已缘浅2024-09-23 13:53:14

您可能需要处理 javax.persistence.RollbackException

You may need to handle javax.persistence.RollbackException

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文