[hibernate-dev] Issue with unidirectional one-to-many association with a join column that references a column that is not the primary key

Marcello Romano marcello74 at gmail.com
Wed Feb 8 15:11:49 EST 2017


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.<init>(CollectionKey.java:58)
at org.hibernate.engine.spi.CollectionKey.<init>(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


More information about the hibernate-dev mailing list