Unidirectional one-to-many with key that is property-ref is broken

Description

Exception:
java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.String
at org.hibernate.type.descriptor.java.StringTypeDescriptor.unwrap(StringTypeDescriptor.java:39)
at org.hibernate.type.descriptor.sql.VarcharTypeDescriptor$1.doBind(VarcharTypeDescriptor.java:64)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:90)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:282)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:277)
at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:56)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2843)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3121)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3587)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:103)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:453)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:345)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1218)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:421)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.hibernate.test.onetoone.OneToOneTest.testOneToOnePropertyRef(OneToOneTest.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Attachments

4

Activity

Former userJune 5, 2018 at 7:35 PM

This is optional in the JPA spec and Hibernate does not support it.

Former userApril 1, 2015 at 11:27 PM

This fix for this issue will likely fix as well.

Former userApril 1, 2015 at 11:18 PM

I've pushed a @FailureExpected test case that reproduces this to master: org/hibernate/test/unidir/BackrefPropertyRefTest .

Former userApril 1, 2015 at 11:11 PM

The problem is in BackrefPropertyAccessor.BackrefGetter.getForInsert(). That method calls StatefulPersistenceContext.getOwnerId(), which returns the ID of the owner, not the collection key.

When a property-ref is used for the collection key, the returned value is (obviously) different from the owner ID.

Currently, this is the only usage of PersistenceContext.getOwnerId(). IMO, this method should be changed to PersistenceContext.getOwnerKey() and the implementation should be changed to return the collection key, not the owner ID.

That would require an SPI change, which can't be done in 4.x. There may be some other very convoluted way to deal with this in 4.x using existing SPIs, but I'm not sure about that.

Former userApril 1, 2015 at 10:33 PM

I believe this is only an issue when using a unidirectional @OneToMany with a join column that references a column that is not the primary key.

Rejected

Details

Assignee

Reporter

Labels

Components

Affects versions

Priority

Created August 29, 2014 at 9:42 AM
Updated December 3, 2024 at 9:06 AM
Resolved June 5, 2018 at 7:35 PM