OneToOneSecondPass Metadata is mistakenly interpreted

Description

I've been tracking an issue that has been causing us some trouble
regarding annotation-based hibernate mappings. The exception occurs at
run-time only:
/org.hibernate.PropertyValueException: not-null property references a
null or transient value ...
/
At first I believed we had an issue with our entity mapping was faulty
and went to try and figure it out... However, I came accross several
examples on the wide internet and showed that my mapping seems
correct. Furthermore, I had some other entities mapped in a similar
fashion that did not cause any issue... How could that be?

I traced the Hibernate code to a class named
org.hibernate.cfg.OneToOneSecondPass (Hibernate Annotations 3.4.0.GA
for those interested to look at the code) up to line 147:

...
Iterator it = otherSide.getJoinIterator();
Join otherSideJoin = null;
while ( it.hasNext() ) {
otherSideJoin = (Join) it.next();
if ( otherSideJoin.containsProperty( otherSideProperty ) ) {
break;
}
}
if ( otherSideJoin != null ) {
...
}
...

If you look closely, it seems that if there are JOINs but none
contains the otherSideProperty, the variable otherSideJoin will not be
null and will contains the last joins of the iterator even if it is
not valid.

The patched-up code would look like:

...
Iterator it = otherSide.getJoinIterator();
Join otherSideJoin = null;
while ( it.hasNext() ) {
Join otherSideJoinValue = (Join) it.next();
if ( otherSideJoinValue.containsProperty( otherSideProperty ) ) {
otherSideJoin = otherSideJoinValue;
break;
}
}
if ( otherSideJoin != null ) {
...
}
...

To fix my issue, I applied this patch:
Index: src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
===================================================================
— src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
(revision 18572)
+++ src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
(working copy)
@@ -146,8 +146,9 @@
Iterator it = otherSide.getJoinIterator();
Join otherSideJoin = null;
while ( it.hasNext() ) {

  • otherSideJoin = (Join) it.next();

  • if ( otherSideJoin.containsProperty(
    otherSideProperty ) ) {
    + Join otherSideJoinValue = (Join) it.next();
    + if ( otherSideJoinValue.containsProperty(
    otherSideProperty ) ) {
    + otherSideJoin = otherSideJoinValue;
    break;
    }
    }

I compiled the code locally and re-tried my failing code and it worked
beautifully. it seemed that my last joins in the iterator has a
nullable = false which caused the runtime
/org.hibernate.PropertyValueException: not-null property references a
null or transient value/

If you take a look at the attached file unit-test.zip which contains a sample of code which reproduce the issue.

The other file attached contains the fixed I applied to the source-code to eliminate the problem

Environment

None

Activity

Show:
Emmanuel Bernard
January 27, 2010, 4:35 PM

Applied.
Thanks Claude.

Strong Liu
January 27, 2010, 4:52 PM
Strong Liu
January 27, 2010, 4:57 PM

reopen to correct the affect version and fix version, will close it soon

Strong Liu
January 27, 2010, 4:59 PM

kk, no it is a hhh issue, no previously annotation version available

fixed in ann v3_3_1_GA_CP and v3_4_0_GA_CP branches

Steve Ebersole
March 21, 2011, 7:08 PM

Bulk closing stale resolved issues

Fixed

Assignee

Emmanuel Bernard

Reporter

Claude Houle

Fix versions

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Major
Configure