Hibernate 6.6.0 lazy loading produces reflection exception

Hello,

this weekend our dependency management switched hibernate + gradle plugin version to 6.6.0.Final, from previously 6.5.2.Final. This caused an unexpected reflection error on our production server:

org.springframework.orm.jpa.JpaSystemException: Error accessing field [public ourcorp.jpa.SkillProfile ourcorp.jpa.UserSkillProfile.skillProfile] by reflection for persistent property [ourcorp.jpa.UserSkillProfile#skillProfile] : 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:341)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:241)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:335)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:160)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:165)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.repository.core.support.MethodInvocationValidator.invoke(MethodInvocationValidator.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
    at jdk.proxy2/jdk.proxy2.$Proxy250.refresh(Unknown Source)
...
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [public ourcorp.jpa.SkillProfile ourcorp.jpa.UserSkillProfile.skillProfile] by reflection for persistent property [ourcorp.jpa.UserSkillProfile#skillProfile] : UserSkillProfilePK(skillProfile=10, person=teamcoord, proficiencyLevel=40)
	at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:52)
	at org.hibernate.metamodel.mapping.internal.AbstractEmbeddableMapping.getValue(AbstractEmbeddableMapping.java:108)
	at org.hibernate.sql.results.graph.embeddable.internal.NonAggregatedIdentifierMappingInitializer.resolveInstanceSubInitializers(NonAggregatedIdentifierMappingInitializer.java:281)
	at org.hibernate.sql.results.graph.embeddable.internal.NonAggregatedIdentifierMappingInitializer.resolveInstance(NonAggregatedIdentifierMappingInitializer.java:268)
	at org.hibernate.sql.results.graph.embeddable.internal.NonAggregatedIdentifierMappingInitializer.resolveInstance(NonAggregatedIdentifierMappingInitializer.java:46)
	at org.hibernate.sql.results.graph.Initializer.resolveInstance(Initializer.java:149)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveInstance(EntityInitializerImpl.java:882)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveInstance(EntityInitializerImpl.java:94)
	at org.hibernate.sql.results.graph.Initializer.resolveInstance(Initializer.java:149)
	at org.hibernate.sql.results.graph.collection.internal.BagInitializer.resolveInstanceSubInitializers(BagInitializer.java:131)
	at org.hibernate.sql.results.graph.collection.internal.AbstractImmediateCollectionInitializer.resolveInstance(AbstractImmediateCollectionInitializer.java:358)
	at org.hibernate.sql.results.graph.collection.internal.AbstractImmediateCollectionInitializer.resolveInstance(AbstractImmediateCollectionInitializer.java:42)
	at org.hibernate.sql.results.graph.Initializer.resolveInstance(Initializer.java:149)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveInstanceSubInitializers(EntityInitializerImpl.java:599)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveInstance(EntityInitializerImpl.java:888)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveInstance(EntityInitializerImpl.java:94)
	at org.hibernate.sql.results.graph.Initializer.resolveInstance(Initializer.java:149)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveInstanceSubInitializers(EntityInitializerImpl.java:599)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveKey(EntityInitializerImpl.java:534)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveKey(EntityInitializerImpl.java:424)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveKey(EntityInitializerImpl.java:94)
	at org.hibernate.sql.results.graph.Initializer.resolveKey(Initializer.java:101)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveKeySubInitializers(EntityInitializerImpl.java:618)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveKey(EntityInitializerImpl.java:498)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveKey(EntityInitializerImpl.java:424)
	at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.resolveKey(EntityInitializerImpl.java:94)
	at org.hibernate.sql.results.internal.StandardRowReader.coordinateInitializers(StandardRowReader.java:235)
	at org.hibernate.sql.results.internal.StandardRowReader.readRow(StandardRowReader.java:141)
	at org.hibernate.sql.results.spi.ListResultsConsumer.readUnique(ListResultsConsumer.java:283)
	at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:195)
	at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:35)
	at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:224)
	at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:102)
	at org.hibernate.sql.exec.spi.JdbcSelectExecutor.executeQuery(JdbcSelectExecutor.java:91)
	at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:165)
	at org.hibernate.loader.ast.internal.SingleIdLoadPlan.load(SingleIdLoadPlan.java:145)
	at org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl.load(SingleIdEntityLoaderStandardImpl.java:89)
	at org.hibernate.persister.entity.AbstractEntityPersister.doLoad(AbstractEntityPersister.java:3778)
	at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3760)
	at org.hibernate.event.internal.DefaultRefreshEventListener.doRefresh(DefaultRefreshEventListener.java:273)
	at org.hibernate.event.internal.DefaultRefreshEventListener.lambda$refresh$0(DefaultRefreshEventListener.java:199)
	at org.hibernate.engine.spi.LoadQueryInfluencers.fromInternalFetchProfile(LoadQueryInfluencers.java:109)
	at org.hibernate.event.internal.DefaultRefreshEventListener.refresh(DefaultRefreshEventListener.java:197)
	at org.hibernate.event.internal.DefaultRefreshEventListener.refresh(DefaultRefreshEventListener.java:184)
	at org.hibernate.event.internal.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:109)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:138)
	at org.hibernate.internal.SessionImpl.fireRefresh(SessionImpl.java:1315)
	at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1276)
	at org.hibernate.engine.spi.CascadingActions$3.cascade(CascadingActions.java:139)
	at org.hibernate.engine.spi.CascadingActions$3.cascade(CascadingActions.java:129)
	at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:550)
	at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:472)
	at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:231)
	at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:584)
	at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:514)
	at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:475)
	at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:231)
	at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:170)
	at org.hibernate.event.internal.DefaultRefreshEventListener.refresh(DefaultRefreshEventListener.java:164)
	at org.hibernate.event.internal.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:109)
	at org.hibernate.event.internal.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:55)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
	at org.hibernate.internal.SessionImpl.fireRefresh(SessionImpl.java:1295)
	at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1246)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:364)
	at jdk.proxy2/jdk.proxy2.$Proxy235.refresh(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:319)
	at jdk.proxy2/jdk.proxy2.$Proxy235.refresh(Unknown Source)
	at ourcorp.jpa.JobRepositoryCustomImpl.refresh(JobRepositoryCustom.kt:203)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720)
	at ourcorp.jpa.JobRepositoryCustomImpl$$SpringCGLIB$$0.refresh(<generated>)
...	 
Caused by: java.lang.IllegalArgumentException: Can not get ourcorp.jpa.SkillProfile field ourcorp.jpa.UserSkillProfile.skillProfile on ourcorp.jpa.pk.UserSkillProfilePK
	at java.base/jdk.internal.reflect.MethodHandleFieldAccessorImpl.newGetIllegalArgumentException(MethodHandleFieldAccessorImpl.java:86)
	at java.base/jdk.internal.reflect.MethodHandleObjectFieldAccessorImpl.get(MethodHandleObjectFieldAccessorImpl.java:61)
	at java.base/java.lang.reflect.Field.get(Field.java:444)
	at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:48)

this happens during the jpa refresh operation of a loaded entity - after calling a modifying legacy stored procedure for the entity. The fun fact is that the entities complained above are linked through a couple of manyToOnes that are marked as fetch lazy and shouldn’t be a problem in the first place.

So I was then comparing the traced queries between version 6.5.2 and 6.6.0 and the result shows that lazy loading was no longer applied with the refresh operation.

So my first assumption is that either the gradle hibernate enhancer plugin stopped working as expected, or something in JPA query optimizer goes really wrong.

Our codebase uses Kotlin 1.9 sources.

Please advise.

There are a lot of elements at play here, as you’re application is using different components other than Hibernate.

Your best course of action to try and get to a solution is to isolate the query / operations leading to this error and trying to reproduce the error you’re encountering by translating your logic, along with the involved entity mappings, to a plain java + Hibernate application. You can find test case templates in our repository which are a good place to start from.

I can work on a test case, but in the meantime, could someone look at the stack trace and see what possibly has gone wrong at the hibernate reflection code there? And compare the relevant code with the 6.5.2 code, as this is the one keg changed that stopped the machine.

Caused by: java.lang.IllegalArgumentException: Can not get ourcorp.jpa.SkillProfile field ourcorp.jpa.UserSkillProfile.skillProfile on ourcorp.jpa.pk.UserSkillProfilePK
	at java.base/jdk.internal.reflect.MethodHandleFieldAccessorImpl.newGetIllegalArgumentException(MethodHandleFieldAccessorImpl.java:86)
	at java.base/jdk.internal.reflect.MethodHandleObjectFieldAccessorImpl.get(MethodHandleObjectFieldAccessorImpl.java:61)
	at java.base/java.lang.reflect.Field.get(Field.java:444)
	at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:48)

I can provide you the kotlin source for that PK now:

package ourcorp.jpa.pk
import lombok.NoArgsConstructor
import java.io.Serializable

@NoArgsConstructor
data class UserSkillProfilePK(
    var skillProfile: Int,
    var person: String,
    var proficiencyLevel: Int,
) : Serializable

I just looked into the JDK source of that root cause:

It fails with a masked class cast exception there - so whatever hibernate fed into the reflection field getter was not of the right type.

Any news on this issue? We are rolling back to Hibernate 5 because of this exact problem

@epol we had no updates from the previous user, and I’m not sure an issue was created in our tracker. If the problem persists with the latest Hibernate version and you want us to look at it, please try reproducing it with our test case templates and create a new ticker in our tracker.

The problem still exists in Hibernate 6.6.2. The last working version was 6.5.2.

I have reserved time this week to produce a bug proof.

I have created an isolated test case. I do not have access to your tracker to create bugs. Instead I uploaded the test case to

The files are based on our production code but pruned to the minimum to make the test case possible.

1 Like

Filed a bug now under HHH-18950

1 Like

My ticket there got closed by a Redhat Engineer having a bad day. I cloned it with improved description (Jira) and it got closed in the next minute by the same engineer. My impression of Redhat/Hibernate support has lost about three stars today.