[hibernate-dev] Issue with unidirectional one-to-many association with a join column that references a column that is not the primary key
Hi, A one-to-many association is causing Hibernate to throw the following exception when loading an entity via Session.get(domainClass, identifier), under the following conditions: 1. the association collection is annotated with @Fetch(FetchMode.JOIN) 2. the association's join column is referencing a non-primary key of the owning entity 3. the association's join column value is referencing a non-existing record of the associated table (the "many" side). Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [protected java.lang.Long ...] by reflection for persistent property [...] : 1GBE4E1E04 at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:43) at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:58) at org.hibernate.type.ComponentType.getPropertyValue(ComponentType.java:419) at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:242) at org.hibernate.engine.spi.CollectionKey.generateHashCode(CollectionKey.java:64) at org.hibernate.engine.spi.CollectionKey.(CollectionKey.java:58) at org.hibernate.engine.spi.CollectionKey.(CollectionKey.java:43) at org.hibernate.engine.loading.internal.CollectionLoadContext.getLoadingCollection(CollectionLoadContext.java:95) at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.finishUpRow(CollectionReferenceInitializerImpl.java:105) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:121) at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:239) at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:122) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86) at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3967) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278) at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129) at org.hibernate.internal.SessionImpl.access$2600(SessionImpl.java:164) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2696) at org.hibernate.internal.SessionImpl.get(SessionImpl.java:975) ... Caused by: java.lang.IllegalArgumentException: Can not set ... to java.lang.String at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168) at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55) at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36) at java.lang.reflect.Field.get(Field.java:379) at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:39) ... 44 more The problem is that when initializing the collection, Hibernate is not able to retrieve the association key value in CollectionReferenceInitializerImpl.finishUpRow and will fall back to use the entity owner's primary key instead, causing the IllegalArgumentException. We have noticed that there is a related open issue: https://hibernate.atlassian.net/browse/HHH-9370 We have worked around this issue by changing the way optionalKey is retrieved in CollectionReferenceInitializerImpl.finishUpRow, foreignKeyPropertyName ); ResultSetProcessingContext.EntityReferenceProcessingState ownerState = context.getOwnerProcessingState( (Fetch) collectionReference ); Serializable optionalKey = collectionReference.getCollectionPersister().getCollectionType().getKeyOfOwner(ownerState.getEntityInstance(), context.getSession()); Although this seems to work for us, we would like to collaborate to have this fixed upstream, if you believe this is actually caused by a bug and not by using Hibernate associations in the wrong way. Thanks, Marcello ___ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev
Re: [hibernate-dev] Issue with unidirectional one-to-many association with a join column that references a column that is not the primary key
Hi Vlad, I have created the following pull request with the test case: https://github.com/hibernate/hibernate-orm/pull/1786 Thanks, Marcello On 8 February 2017 at 15:35, Vlad Mihalcea wrote: > Hi, > > You can send us a Pull Request on GitHub with a test case that replicates > it, so we can discuss and integrate it. > > Vlad > > On Wed, Feb 8, 2017 at 10:11 PM, Marcello Romano > wrote: > >> Hi, >> >> A one-to-many association is causing Hibernate to >> throw the following exception when loading an entity via >> Session.get(domainClass, identifier), under the following conditions: >> >> 1. the association collection is annotated with @Fetch(FetchMode.JOIN) >> 2. the association's join column is referencing a non-primary key of the >> owning entity >> 3. the association's join column value is referencing a non-existing >> record >> of the associated table (the "many" side). >> >> Caused by: org.hibernate.property.access.spi.PropertyAccessException: >> Error >> accessing field [protected java.lang.Long ...] by reflection for >> persistent >> property [...] : 1GBE4E1E04 >> at >> org.hibernate.property.access.spi.GetterFieldImpl.get(Getter >> FieldImpl.java:43) >> at >> org.hibernate.tuple.component.AbstractComponentTuplizer.getP >> ropertyValue(AbstractComponentTuplizer.java:58) >> at org.hibernate.type.ComponentType.getPropertyValue(ComponentT >> ype.java:419) >> at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:242) >> at >> org.hibernate.engine.spi.CollectionKey.generateHashCode(Coll >> ectionKey.java:64) >> at org.hibernate.engine.spi.CollectionKey.(CollectionKey.java:58) >> at org.hibernate.engine.spi.CollectionKey.(CollectionKey.java:43) >> at >> org.hibernate.engine.loading.internal.CollectionLoadContext. >> getLoadingCollection(CollectionLoadContext.java:95) >> at >> org.hibernate.loader.plan.exec.process.internal.CollectionRe >> ferenceInitializerImpl.finishUpRow(CollectionReferenc >> eInitializerImpl.java:105) >> at >> org.hibernate.loader.plan.exec.process.internal.AbstractRowR >> eader.readRow(AbstractRowReader.java:121) >> at >> org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetai >> ls$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:239) >> at >> org.hibernate.loader.plan.exec.process.internal.ResultSetPro >> cessorImpl.extractResults(ResultSetProcessorImpl.java:122) >> at >> org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBase >> dLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122) >> at >> org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBase >> dLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86) >> at >> org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntity >> Loader.load(AbstractLoadPlanBasedEntityLoader.java:167) >> at >> org.hibernate.persister.entity.AbstractEntityPersister.load( >> AbstractEntityPersister.java:3967) >> at >> org.hibernate.event.internal.DefaultLoadEventListener.loadFr >> omDatasource(DefaultLoadEventListener.java:508) >> at >> org.hibernate.event.internal.DefaultLoadEventListener.doLoad >> (DefaultLoadEventListener.java:478) >> at >> org.hibernate.event.internal.DefaultLoadEventListener.load(D >> efaultLoadEventListener.java:219) >> at >> org.hibernate.event.internal.DefaultLoadEventListener.proxyO >> rLoad(DefaultLoadEventListener.java:278) >> at >> org.hibernate.event.internal.DefaultLoadEventListener.doOnLo >> ad(DefaultLoadEventListener.java:121) >> at >> org.hibernate.event.internal.DefaultLoadEventListener.onLoad >> (DefaultLoadEventListener.java:89) >> at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129) >> at org.hibernate.internal.SessionImpl.access$2600(SessionImpl.java:164) >> at >> org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl. >> load(SessionImpl.java:2696) >> at org.hibernate.internal.SessionImpl.get(SessionImpl.java:975) >> ... >> Caused by: java.lang.IllegalArgumentException: Can not set ... to >> java.lang.String >> at >> sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException( >> UnsafeFieldAccessorImpl.java:164) >> at >> sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException( >> UnsafeFieldAccessorImpl.java:168) >> at >> sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAcc >> essorImpl.java:55) >> at >> sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFi >> eldAccessorI