[JIRA] (HHH-15778) Fetching an Entity with a lazily loaded Embeddable with more fields than the parent results in an ArrayIndexOutOfBoundsException
by Georg Echterling (JIRA)
Georg Echterling ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiNzRmMTU4M2Qx... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-15778?atlOrigin=eyJpIjoiNzRmMT... ) HHH-15778 ( https://hibernate.atlassian.net/browse/HHH-15778?atlOrigin=eyJpIjoiNzRmMT... ) Fetching an Entity with a lazily loaded Embeddable with more fields than the parent results in an ArrayIndexOutOfBoundsException ( https://hibernate.atlassian.net/browse/HHH-15778?atlOrigin=eyJpIjoiNzRmMT... )
Change By: Georg Echterling ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
Fetching an Entity containing an Embeddable fails if the Embeddable has more fields than the Entity and is not loaded eagerly. This exception happens before the Entity is loaded from the database.
{code:none}java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
at org.hibernate.metamodel.mapping.internal.BasicAttributeMapping.generateFetch(BasicAttributeMapping.java:304)
at org.hibernate.sql.results.graph.FetchParent.generateFetchableFetch(FetchParent.java:105)
at org.hibernate.loader.ast.internal.LoaderSelectBuilder.lambda$createFetchableBiConsumer$5(LoaderSelectBuilder.java:833)
at org.hibernate.loader.ast.internal.LoaderSelectBuilder.visitFetches(LoaderSelectBuilder.java:672)
at org.hibernate.loader.ast.internal.LoaderSqlAstCreationState.visitFetches(LoaderSqlAstCreationState.java:123)
at org.hibernate.sql.results.graph.AbstractFetchParent.afterInitialize(AbstractFetchParent.java:32)
at org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl.<init>(EmbeddableFetchImpl.java:75)
at org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping.generateFetch(EmbeddedAttributeMapping.java:238)
at org.hibernate.sql.results.graph.FetchParent.generateFetchableFetch(FetchParent.java:105)
at org.hibernate.loader.ast.internal.LoaderSelectBuilder.lambda$createFetchableBiConsumer$5(LoaderSelectBuilder.java:833)
at org.hibernate.loader.ast.internal.LoaderSelectBuilder.visitFetches(LoaderSelectBuilder.java:672)
at org.hibernate.loader.ast.internal.LoaderSqlAstCreationState.visitFetches(LoaderSqlAstCreationState.java:123)
at org.hibernate.sql.results.graph.AbstractFetchParent.afterInitialize(AbstractFetchParent.java:32)
at org.hibernate.sql.results.graph.entity.AbstractEntityResultGraphNode.afterInitialize(AbstractEntityResultGraphNode.java:100)
at org.hibernate.persister.entity.AbstractEntityPersister.createDomainResult(AbstractEntityPersister.java:1298)
at org.hibernate.loader.ast.internal.LoaderSelectBuilder.generateSelect(LoaderSelectBuilder.java:451)
at org.hibernate.loader.ast.internal.LoaderSelectBuilder.createSelect(LoaderSelectBuilder.java:178)
at org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl.createLoadPlan(SingleIdEntityLoaderStandardImpl.java:180)
at org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl.resolveLoadPlan(SingleIdEntityLoaderStandardImpl.java:153)
at org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl.load(SingleIdEntityLoaderStandardImpl.java:66)
at org.hibernate.persister.entity.AbstractEntityPersister.doLoad(AbstractEntityPersister.java:4380)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4370)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:590)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromCacheOrDatasource(DefaultLoadEventListener.java:576)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:545)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:538)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:200)
at org.hibernate.event.internal.DefaultLoadEventListener.loadWithRegularProxy(DefaultLoadEventListener.java:280)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:235)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:104)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:76)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118)
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1221)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1209)
at org.hibernate.loader.access.IdentifierLoadAccessImpl.doLoad(IdentifierLoadAccessImpl.java:192)
at org.hibernate.loader.access.IdentifierLoadAccessImpl.lambda$load$1(IdentifierLoadAccessImpl.java:158)
at org.hibernate.loader.access.IdentifierLoadAccessImpl.perform(IdentifierLoadAccessImpl.java:105)
at org.hibernate.loader.access.IdentifierLoadAccessImpl.load(IdentifierLoadAccessImpl.java:158)
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:2336)
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:2303)
at org.hibernate.orm.test.query.sql.EmbeddableLazyFetchTest.lambda$testSelect$2(EmbeddableLazyFetchTest.java:60)
at org.hibernate.testing.orm.transaction.TransactionUtil.wrapInTransaction(TransactionUtil.java:49)
at org.hibernate.testing.orm.transaction.TransactionUtil.inTransaction(TransactionUtil.java:24)
at org.hibernate.testing.orm.junit.SessionFactoryExtension$SessionFactoryScopeImpl.inTransaction(SessionFactoryExtension.java:375)
at org.hibernate.testing.orm.junit.SessionFactoryExtension$SessionFactoryScopeImpl.inTransaction(SessionFactoryExtension.java:352)
at org.hibernate.orm.test.query.sql.EmbeddableLazyFetchTest.testSelect(EmbeddableLazyFetchTest.java:56){code}
BasicAttributeMapping.generateFetch seems to load the Entity’s property laziness with the Embeddable’s property index.
Since this bug is very similar to [https://hibernate.atlassian.net/browse/HHH-15658|https://hibernate.atlass...], I have adapted its test case. In the test, the Embeddable is loaded lazily because it is omitted from the EntityGraph:
{code:java}package org.hibernate.orm.test.query.sql;
import java.util.Collections;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@DomainModel(
annotatedClasses = EmbeddableLazyFetchTest.Person.class
)
@SessionFactory
@TestForIssue(jiraKey = " HHH-15778 ")
public class EmbeddableLazyFetchTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Address address = new Address( "Milan", "Italy", "Italy", "20133" );
Person person = new Person( 1, address );
session.persist( person );
}
);
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
session ->
session.createMutationQuery( "delete from Person" ).executeUpdate()
);
}
@Test
public void testSelect(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
RootGraphImplementor<Person> graph = session.createEntityGraph( Person.class );
Person person = session.find(
Person.class, 1,
Collections.singletonMap( "jakarta.persistence.fetchgraph", graph )
);
assertThat( person ).isNotNull();
}
);
}
@Entity(name = "Person")
public static class Person {
@Id
private Integer id;
private Address address;
public Person() {
}
public Person(Integer id, Address address) {
this.id = id;
this.address = address;
}
}
@Embeddable
public static class Address {
private String city;
private String state;
private String country;
private String postcode;
public Address() {
}
public Address(String city, String state, String country, String postcode) {
this.city = city;
this.state = state;
this.country = country;
this.postcode = postcode;
}
}
}{code}
( https://hibernate.atlassian.net/browse/HHH-15778#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-15778#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100210- sha1:4037f92 )