Regression: optional properties under a <join> tag no longer update properly

Description

This was specifically introduced with the revision 10217 changes on the 3.2 branch in src/org/hibernate/persister/entity/AbstractEntityPersister.java

Given the following setup:

<class name="Thing">
<id .../>
<join table="JOIN_TABLE" optional="true">
<key column="THING_ID" not-null="true"/>
<property name="joinedProperty" column="JOINED_PROPERTY"/>
</join>
</class>

scenario:
Thing thing1 = new Thing();
thing1.setJoinedProperty("thing1");
save(thing1);
// a record in the JOIN_TABLE is created properly and updates on the property can occur

Thing thing2 = new Thing();
thing2.setJoinedProperty(null);
save(thing2);
// no record in JOIN_TABLE is created

thing2.setJoinedProperty("thing2");
save(thing2);
// in revision 10216, hibernate correctly runs an INSERT to create a JOIN_TABLE record with the value "thing2"
// in revision 10217, hibernate incorrectly runs an UPDATE to try and update a non-existant record in the JOIN_TABLE with the thing2 id

It looks like the expectation.verifyOutcome() method should be throwing a StaleStateException if the attempted update effects 0 rows.

I will try and get an official hibernate testcase going and possibly a patch, but I wanted to enter this now in case there is something I'm missing that makes this change in functionality intentional.

Environment

hibernate 3.2.0.cr4 through 3.2.1.ga
hsql 1.8.0.7 and Oracle 9i

Activity

Show:
ChrisJ
December 21, 2006, 4:47 AM

OptionalJoinTest/OptionalJoinTest.java
OptionalJoinTest/Thing.hbm.xml
OptionalJoinTest/Thing.java

these go in:
test/org/hibernate/test/join

ChrisJ
December 21, 2006, 4:51 AM

Added a test for this. I had to open/close the session in between operations to replicate this fully.

Gail Badner
April 5, 2007, 11:36 PM

I'm attaching a patch for this issue. I've tested it using the test case attached to this ticket. I've also run the unit tests using this patch and it did not seem to introduce any problems.

This patch contains the following changes:

  • adds determineRowCount() to the Expectation interface and makes protected implementations public

  • adds method Expectations::NONE.determineRowCount() which always returns -2, which means that the number of affected rows is unknown

  • changes AbstractEntityPersister.check() to return:
    expectation.determineRowCount(rows, statement) > 0
    when StaleStateException is caught and the table is "nullable" (e.g., association is optional)

This should only change the behavior of the method when the number of affected rows is less than expected, the table is "nullable", and no rows were updated. When these conditions are satisfied, false will be returned.

Gail Badner
SourceLabs - http://www.sourcelabs.com
Dependable Open Source Systems

Gail Badner
April 5, 2007, 11:43 PM

I am attaching a patch that adds OptionalJoinTest (provided by Chris Joins) to a new test suite, org.hibernate.test.join.JoinSuite. I made one minor change to do a check in a separate transaction and changed indentations from spaces to tabs.

Gail Badner
SourceLabs - http://www.sourcelabs.com
Dependable Open Source Systems

Gail Badner
August 16, 2007, 12:41 AM

Fixed in trunk / 3.2.

Assignee

Gail Badner

Reporter

ChrisJ

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