Skip to content

Hibernate 6 ArrayIndexOutOfBoundsException for custom types (such as JSON) when using Single Table Inheritance #739

Description

@Stephen-Allen

Describe the bug
In Hibernate 6, an ArrayIndexOutOfBoundsException is thrown for custom types (such as JSON) when using Single Table Inheritance and children have the same property name and type.

To Reproduce
See attached unit test using @Type(JsonType.class). If you change the property to Hibernate's built in @JdbcTypeCode(SqlTypes.JSON) then it works as expected.

java.lang.ArrayIndexOutOfBoundsException: Index 2 out of bounds for length 2

	at org.hibernate.persister.entity.AbstractEntityPersister.selectFragment(AbstractEntityPersister.java:1908)
	at org.hibernate.query.sql.internal.SQLQueryParser.resolveProperties(SQLQueryParser.java:236)
	at org.hibernate.query.sql.internal.SQLQueryParser.substituteBrackets(SQLQueryParser.java:159)
	at org.hibernate.query.sql.internal.SQLQueryParser.process(SQLQueryParser.java:64)
	at org.hibernate.query.sql.internal.NativeSelectQueryPlanImpl.<init>(NativeSelectQueryPlanImpl.java:53)
	at org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl.createQueryPlan(NativeQueryInterpreterStandardImpl.java:45)
	at org.hibernate.query.sql.internal.NativeQueryImpl.createQueryPlan(NativeQueryImpl.java:688)
	at org.hibernate.query.sql.internal.NativeQueryImpl.lambda$resolveSelectQueryPlan$7(NativeQueryImpl.java:651)
	at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.resolveSelectQueryPlan(QueryInterpretationCacheStandardImpl.java:83)
	at org.hibernate.query.sql.internal.NativeQueryImpl.resolveSelectQueryPlan(NativeQueryImpl.java:651)
	at org.hibernate.query.sql.internal.NativeQueryImpl.doList(NativeQueryImpl.java:628)
	at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:423)
	at org.hibernate.query.spi.AbstractSelectionQuery.getSingleResult(AbstractSelectionQuery.java:555)
	at io.hypersistence.utils.hibernate.type.json.generic.GenericH2JsonMapSingleTableInheritanceTest.lambda$test$1(GenericH2JsonMapSingleTableInheritanceTest.java:67)
	at io.hypersistence.utils.test.AbstractHibernateTest.doInJPA(AbstractHibernateTest.java:494)
	at io.hypersistence.utils.hibernate.type.json.generic.GenericH2JsonMapSingleTableInheritanceTest.test(GenericH2JsonMapSingleTableInheritanceTest.java:62)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	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.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.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)

Expected behavior
The select statement should only select the field a single time and it should be shared between the subclasses.

Additional context
I believe this is caused by SqlAstQueryPartProcessingStateImpl line 158 in Hibernate expecting that the type references are equal, but instead for hypersistence they are two different objects (but are the same internally). I could not figure out how to ensure Hibernate gets the same object reference each time @Type(JsonType.class) is used instead of new instances of the object.

Unit_test_for_Single_Table_Inheritance_bug.patch

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions