Hibernate doesn't support optional one-to-one associations
----------------------------------------------------------
Key: HHH-2007
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2007
Project: Hibernate3
Type: Bug
Components: core
Versions: 3.2.0.cr2
Reporter: Andrei Iltchenko
Hibernate doesn't properly support optional one-to-one associations, e.g. Person
(0..1) -- (0..1) Passport.
The Hibernate books and reference all talk of two ways of mapping one-to-one associations:
1. using a many-to-one fk association with a unique constraint on the fk;
2. using a pk association.
the trouble with both of them is that they enforce the mandatory property of an
association end, which sometimes is not desirable. The first way enforces the mandatory
property with the uniqueness constraint on the fk, the other by using the fact that one
table's pk is its fk.
I tried to see if I could adapt the 1st way of representing one-to-ones to
support optional association ends. What I did was simply remove the unique and not null
constrains from DDL generated (without removing it it would be impossible to have a Person
record that doesn't reference a Passport record):
from
CREATE TABLE Person (
PassUniqueId VARCHAR (32) NOT NULL,
version INTEGER NOT NULL,
uniqueId VARCHAR (32) NOT NULL,
name VARCHAR (40) NULL,
PRIMARY KEY (uniqueId),
UNIQUE(PassUniqueId),
FOREIGN KEY (PassUniqueId) REFERENCES Passport (uniqueId)
);
to
CREATE TABLE Person (
PassUniqueId VARCHAR (32) NULL,
version INTEGER NOT NULL,
uniqueId VARCHAR (32) NOT NULL,
name VARCHAR (40) NULL,
PRIMARY KEY (uniqueId),
FOREIGN KEY (PassUniqueId) REFERENCES Passport (uniqueId)
);
but leave the uniqueness attribute in the mapping file:
<many-to-one
name="pass"
class="application.business.logic.Passport"
cascade="save-update,merge"
unique="true"
<column name="PassUniqueId"/>
</many-to-one>
The resulting solution worked fine and I was able to create instances of Person not linked
to a Passport. However Hibernate didn't succed in keeping the association from
degrading into a many-to-one. It enabled me to create two Persons linked with the same
Passport:
PASSUNIQUEID | VIRSION | UNIQUEID | Name
================================================
0d8b3919fffff | 1 | 0d5fb1dcfff | John
0d8b3919fffff | 0 | 10fd07bdfff | Sam
A subsequent attempt at retrieving such Persons with Hibernate failed:
org.hibernate.HibernateException: More than one row with the given identifier was found:
0d8b3919ffffffd60151e135b6da0164, for class: application.business.logic.Passport.
Hibernate should be able to impose the single end property of such associations without
relying on the underlying RDBMS engine and never allow them to degrade to many-to-ones.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira