Inconsistent handling of @Embedded objects wrt null attributes
--------------------------------------------------------------
Key: HHH-6981
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-6981
Project: Hibernate ORM
Issue Type: Bug
Components: annotations, core
Affects Versions: 3.6.9
Environment: Discovered in Hibernate 3.6.2, verified against Hibernate 3.6.9.
Database platform probably irrelevant? (Verified against Oracle JDBC and H2)
Reporter: Maxime Gamboni
First of all, I have to say I am not yet very fluent in Hibernate. I started working on a
pre-existing codebase so some subtleties of this are surely escaping me and this is also
the reason I might have trouble creating a test case for this bug. I was also not sure
which Components to select in this bug report.
Say I have a class A with an @Embedded component B b.
Step 1:
If I saveOrUpdate an instance A a such that:
1) a.b is not null
2) All attributes of a.b.xyz are null
3) All other attributes a.xyz (except from the identifier in case of an update) are null:
This produces a row in the database with all attributes set to null.
Step 2:
If I then attempt to update the object with a separate invocation of saveOrUpdate where
a.b is still not null but values of other attributes are irrelevant, Hibernate will
execute an insert instead of an update, causing a "Unique index or primary key
violation".
I tracked this down to the
org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert method:
In step 1, fields contains a non-null B instance, so isAllNull( fields, j ) returns false,
so the row is updated with all null values. It is NOT deleted.
In step 2:
1) The oldFields array contains only null values (including the 'b' attribute),
causing isAllNull( oldFields, j ) to return true.
2) oldFields itself is not null (in my case, A was part, but not embedded, in another
entity that had non-null values for fields outside of table 'j'. Is this
relevant?).
This causes the first test to return true, and sets isRowToUpdate to true, so we invoke
the insert() method, which fails as we already have a row with the same identifier.
My workaround was to make sure my objects never contain an instance of B whose attributes
are all null but this is not ideal. Dropping the test
if ( isNullableTable( j ) && oldFields != null && isAllNull( oldFields, j
) ) isRowToUpdate = false;
would probably solve the problem, but probably at the cost of a lesser efficiency in other
cases.
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira