DynamicUpdate / DynamicInsert with batching leads to parameter binding exception

Description

Given

  • STATEMENT_BATCH_SIZE is enabled

  • An entity with DynamicUpdate

When

  • When changing multiple instances of a managed entity

Then

  • An exception occurs trying to bind a parameter using the wrong generated sql

 

@DynamicUpdate @Entity @Table(name = "ENTITY_A") public class EntityA { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") Integer id; @Column(name = "PROPERTY_A") int propertyA; @Column(name = "PROPERTY_B") int propertyB; }
@Override protected void configure(Configuration configuration) { super.configure(configuration); configuration.setProperty(AvailableSettings.SHOW_SQL, Boolean.TRUE.toString()); configuration.setProperty(AvailableSettings.FORMAT_SQL, Boolean.TRUE.toString()); configuration.setProperty(AvailableSettings.STATEMENT_BATCH_SIZE, "2"); } @Test public void hhhXXXXTest() throws Exception { // BaseCoreFunctionalTestCase automatically creates the SessionFactory and // provides the Session. try (Session s = openSession()) { Transaction tx = s.beginTransaction(); EntityA entityA1 = new EntityA(); EntityA entityA2 = new EntityA(); s.persist(entityA1); s.persist(entityA2); tx.commit(); } try (Session s = openSession()) { Transaction tx = s.beginTransaction(); String hql = "select e from org.hibernate.bugs.EntityA e"; Query<EntityA> query = s.createQuery(hql, EntityA.class); List<EntityA> actual = query.list(); actual.get(0).propertyA = 1; actual.get(1).propertyA = 2; actual.get(1).propertyB = 2; s.flush(); tx.commit(); } }
org.hibernate.exception.DataException: Unable to bind parameter #3 - 2 [Invalid value "3" for parameter "parameterIndex" [90008-214]] [n/a] at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:53) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:94) at org.hibernate.engine.jdbc.mutation.internal.JdbcValueBindingsImpl.lambda$beforeStatement$0(JdbcValueBindingsImpl.java:95) at java.base/java.lang.Iterable.forEach(Iterable.java:75) at org.hibernate.engine.jdbc.mutation.spi.BindingGroup.forEachBinding(BindingGroup.java:51) at org.hibernate.engine.jdbc.mutation.internal.JdbcValueBindingsImpl.beforeStatement(JdbcValueBindingsImpl.java:85) at org.hibernate.engine.jdbc.batch.internal.BatchImpl.lambda$addToBatch$0(BatchImpl.java:129) at org.hibernate.engine.jdbc.mutation.internal.PreparedStatementGroupSingleTable.forEachStatement(PreparedStatementGroupSingleTable.java:59) at org.hibernate.engine.jdbc.batch.internal.BatchImpl.addToBatch(BatchImpl.java:114) at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleBatched.performBatchedOperations(MutationExecutorSingleBatched.java:60) at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:45) at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.doDynamicUpdate(UpdateCoordinatorStandard.java:939) at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.performUpdate(UpdateCoordinatorStandard.java:279) at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.coordinateUpdate(UpdateCoordinatorStandard.java:209) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2739) at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:166) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:616) at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:487) at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:484) at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:358) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1398) at org.hibernate.bugs.ORMUnitTestCase.hhhXXXXXTest(ORMUnitTestCase.java:80) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: org.h2.jdbc.JdbcSQLDataException: Invalid value "3" for parameter "parameterIndex" [90008-214] at org.h2.message.DbException.getJdbcSQLException(DbException.java:646) at org.h2.message.DbException.getJdbcSQLException(DbException.java:477) at org.h2.message.DbException.get(DbException.java:223) at org.h2.message.DbException.getInvalidValueException(DbException.java:298) at org.h2.jdbc.JdbcPreparedStatement.setParameter(JdbcPreparedStatement.java:1395) at org.h2.jdbc.JdbcPreparedStatement.setInt(JdbcPreparedStatement.java:359) at org.hibernate.type.descriptor.jdbc.IntegerJdbcType$1.doBind(IntegerJdbcType.java:72) at org.hibernate.type.descriptor.jdbc.BasicBinder.bind(BasicBinder.java:61) at org.hibernate.engine.jdbc.mutation.internal.JdbcValueBindingsImpl.lambda$beforeStatement$0(JdbcValueBindingsImpl.java:87) ... 38 more

 

Test scenario attached and also available here https://github.com/ratoaq2/HHH-16352

Attachments

1
  • 22 Mar 2023, 01:06 PM

Activity

Show:

Steve Ebersole March 27, 2023 at 11:59 PM

This affects dynamic inserts as well, right ?

Jan Schatteman March 23, 2023 at 4:38 PM
Edited

Looking into this, I found that (as a temporary workaround) you could set the batch size directly on the Session, it does not seem to happen then.

Scratch that, and please pretend you didn’t see it, my mistake, sorry.

Fixed

Details

Assignee

Reporter

Worked in

Components

Fix versions

Affects versions

Priority

Created March 22, 2023 at 1:03 PM
Updated April 14, 2023 at 8:21 AM
Resolved April 12, 2023 at 3:13 PM