首页 > 解决方案 > JPA + Hibernate:org.hibernate.exception.ConstraintViolationException:无法执行批处理

问题描述

我想使用 hibernate 提供的批量插入/更新(使用 MySQL 5.7),如本文中给出的那样
我知道我们不能对具有 id 生成为 IDENTITY 的实体使用批量插入/更新。
更多信息:如果您使用 IDENTITY 标识符生成器,​​Hibernate 会透明地禁用 JDBC 级别的插入批处理。
因此,我更改@GeneratedValue(strategy = GenerationType.IDENTITY)@GeneratedValue(strategy = GenerationType.SEQUENCE)其中一个休眠实体并开始收到以下错误。

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1443) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1423) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_172]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_172]
    at java.lang.Thread.run(Thread.java:748) [?:1.8.0_172]
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:112) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:128) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.addToBatch(BatchingBatch.java:88) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3026) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3547) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:600) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:474) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1437) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    ... 7 more
Caused by: java.sql.BatchUpdateException: Duplicate entry '1002' for key 'PRIMARY'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_172]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0_172]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_172]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_172]
    at com.mysql.cj.util.Util.handleNewInstance(Util.java:191) ~[mysql-connector-java-8.0.13.jar:8.0.13]
    at com.mysql.cj.util.Util.getInstance(Util.java:166) ~[mysql-connector-java-8.0.13.jar:8.0.13]
    at com.mysql.cj.util.Util.getInstance(Util.java:173) ~[mysql-connector-java-8.0.13.jar:8.0.13]
    at com.mysql.cj.jdbc.exceptions.SQLError.createBatchUpdateException(SQLError.java:224) ~[mysql-connector-java-8.0.13.jar:8.0.13]
    at com.mysql.cj.jdbc.ClientPreparedStatement.executeBatchedInserts(ClientPreparedStatement.java:776) ~[mysql-connector-java-8.0.13.jar:8.0.13]
    at com.mysql.cj.jdbc.ClientPreparedStatement.executeBatchInternal(ClientPreparedStatement.java:447) ~[mysql-connector-java-8.0.13.jar:8.0.13]
    at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:814) ~[mysql-connector-java-8.0.13.jar:8.0.13]
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:2544) ~[c3p0-0.9.5.2.jar:0.9.5.2]
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:118) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.addToBatch(BatchingBatch.java:88) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3026) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3547) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:600) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:474) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1437) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    ... 7 more

这些是我用于配置的休眠设置。

extraProperties.put(Environment.ORDER_UPDATES, true);
extraProperties.put(Environment.ORDER_INSERTS, true);
extraProperties.put(Environment.BATCH_VERSIONED_DATA, true);
extraProperties.put(Environment.USE_SECOND_LEVEL_CACHE, false);
extraProperties.put(Environment.USE_GET_GENERATED_KEYS, false);
extraProperties.put(Environment.SHOW_SQL, true);
extraProperties.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
extraProperties.put(Environment.STATEMENT_BATCH_SIZE, 100);

似乎 id 已经存在于数据库中。
我需要做更多的改变来改变GenerationType吗?
任何帮助,将不胜感激。提前致谢

标签: javahibernatejpa

解决方案


要使用@GeneratedValue(strategy = GenerationType.SEQUENCE)数据库引擎必须支持序列。

序列是一个单独的数据库对象。(更多信息:https ://www.geeksforgeeks.org/sql-sequences/ )

MySql 不支持序列。所以你不能以这种形式使用注释。另请阅读@SequenceGeneratorhttps ://thorben-janssen.com/jpa-generate-primary-keys 。

但是你可以尝试一些 Hibernate 技巧,SequenceStyleGenerator这里描述了https://www.baeldung.com/hibernate-identifiers


推荐阅读