From e82b8c80f066cbcc2d6bd2f05c5e066ff6cb55ef Mon Sep 17 00:00:00 2001 From: rbygrave Date: Tue, 13 Jul 2021 11:30:31 +1200 Subject: [PATCH] #2265 - ArrayIndexOutOfBoundsException: Index -1 out of bounds with @IdClass and batch insert accessing id property --- .../server/core/PersistRequestBean.java | 8 ++++--- .../server/deploy/BeanDescriptor.java | 10 +++++++- .../tests/model/bridge/TestIdClassScalar.java | 24 +++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java index ce6a39878..8b3285c7a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java @@ -379,9 +379,11 @@ public final class PersistRequestBean extends PersistRequest implements BeanP public void setBatched() { batched = true; if (type == Type.INSERT || type == Type.UPDATE) { - // used to trigger automatic jdbc batch flush - intercept.registerGetterCallback(this); - getterCallback = true; + if (beanDescriptor.hasSingleIdProperty()) { + // used to trigger automatic jdbc batch flush + intercept.registerGetterCallback(this); + getterCallback = true; + } } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java index 326cbae00..260985417 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java @@ -1747,6 +1747,13 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType { return idProperty != null; } + /** + * Return false for IdClass case with multiple @Id properties. + */ + public boolean hasSingleIdProperty() { + return idPropertyIndex != -1; + } + /** * Return true if this type has a simple Id and the platform supports mutli-value binding. */ @@ -3145,7 +3152,8 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType { } public boolean isIdLoaded(EntityBeanIntercept ebi) { - return ebi.isLoadedProperty(idPropertyIndex); + // assume id loaded for IdClass case with idPropertyIndex == -1 + return idPropertyIndex == -1 ? true : ebi.isLoadedProperty(idPropertyIndex); } boolean hasIdValue(EntityBean bean) { diff --git a/ebean-core/src/test/java/org/tests/model/bridge/TestIdClassScalar.java b/ebean-core/src/test/java/org/tests/model/bridge/TestIdClassScalar.java index 06b2ee143..a06c7e173 100644 --- a/ebean-core/src/test/java/org/tests/model/bridge/TestIdClassScalar.java +++ b/ebean-core/src/test/java/org/tests/model/bridge/TestIdClassScalar.java @@ -1,7 +1,9 @@ package org.tests.model.bridge; import io.ebean.BaseTestCase; +import io.ebean.DB; import io.ebean.Ebean; +import io.ebean.Transaction; import org.ebeantest.LoggedSqlCollector; import org.junit.Test; @@ -39,6 +41,28 @@ public class TestIdClassScalar extends BaseTestCase { } + @Test + public void insertBatch() { + UUID siteId = UUID.randomUUID(); + UUID userId = UUID.randomUUID(); + + try (final Transaction transaction = DB.beginTransaction()) { + transaction.setBatchMode(true); + + + BSiteUserD access = new BSiteUserD(BAccessLevel.ONE, siteId, userId); + DB.save(access); + + final UUID siteId1 = access.getSiteId(); // ArrayIndexOutOfBoundsException here + assertThat(siteId1).isNotNull(); + assertThat(access.getUserId()).isEqualTo(userId); + + transaction.commit(); + } + + DB.delete(BSiteUserD.class, new BEmbId(siteId, userId)); + } + @Test public void test() {