java - 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
吗?
任何帮助,将不胜感激。提前致谢
解决方案
要使用@GeneratedValue(strategy = GenerationType.SEQUENCE)
数据库引擎必须支持序列。
序列是一个单独的数据库对象。(更多信息:https ://www.geeksforgeeks.org/sql-sequences/ )
MySql 不支持序列。所以你不能以这种形式使用注释。另请阅读@SequenceGenerator
:https ://thorben-janssen.com/jpa-generate-primary-keys 。
但是你可以尝试一些 Hibernate 技巧,SequenceStyleGenerator
这里描述了https://www.baeldung.com/hibernate-identifiers。
推荐阅读
- python - 根据 pandas 中的时间戳差异条件提取值
- auth0 - 用户立即被重定向到 Auth0 登录页面,而不是登陆 IndexPage
- c# - 如何实现 SqlDataAdapter 的异步更新方法?
- http - MS Edge 无法处理部分内容 (206) 响应
- r - Geom_violin + geom_error_bar
- c# - VS2019 扩展使用 IDebugEventCallback2
- android - 发送通知时自动打开活动而不点击通知
- java - 如何解决此 java 错误“java.io.IOException: invalid constant type: 19 at 3”
- javascript - mobx/mobx-state-tree 中的可重用操作
- javascript - 使用 Ionic 4 + angular 的时间记录器