It appears that there is no way to get cascading insert and lazy loading to work using the same one-to-one mapping definition.
In the docs/code below, I am attempting to use constrained="true" so that lazy load will work. But when I use this then my cascading insert fails. Hibernate seems to be trying to insert the child (User) before the parent (Person), and it has a null id.
If I switch to use constrained="false" then the cascading insert works, but then the load is always "eager."
We have tried every permiatation we can think of, but with no success. The only example that is close to detailed I read here:
http://forum.hibernate.org/viewtopic.ph ... toone+lazy. However, from what I can see the child's id is "assigned" rather than "foreign". I believe this implies that my parent (Person) would have to be saved before the child (User), and then the parent's id would be assigned to the child manually by the app.
That is not a desirable solution for us.
HELP!
Hibernate version: 2.1
Mapping documents:
Code:
<hibernate-mapping package="mappings.one_to_one">
<class name="Person" table="PERSON">
<id name="oid" column="PERSON_SEQ_NO">
<generator class="native"/>
</id>
<property name="firstName" column="FIRST_NAME"/>
<property name="lastName" column="LAST_NAME"/>
<property name="middleName" column="MIDDLE_NAME"/>
<one-to-one name="user" class="User" constrained="true" outer-join="false"/>
</class>
</hibernate-mapping>
<hibernate-mapping package="mappings.one_to_one">
<class name="User" table="USER" proxy="User">
<id name="oid" column="PERSON_SEQ_NO">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="password" column="PASSWORD"/>
<property name="username" column="USERNAME"/>
<one-to-one name="person" class="Person" constrained="true" />
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
// inside a JUnit test . . .
PersonIF tempPerson = new Person();
tempPerson.setFirstName("Vaughn");
tempPerson.setLastName("Vernon");
tempPerson.setMiddleName("L");
UserIF tempUser = new User();
tempUser.setPassword("pw");
tempUser.setUsername("vvernon");
tempPerson.setUser(tempUser);
tempUser.setPerson(tempPerson);
Session tempSession = this.getSession();
// core create test
Transaction tempTx = tempSession.beginTransaction();
tempSession.save(tempPerson);
tempTx.commit();
tempSession.close();
// follow up with read test
tempSession = this.getSession(); // make sure not cached instance
Long tempOid = ((Person) tempPerson).getOid();
tempTx = tempSession.beginTransaction();
tempPerson = (PersonIF) tempSession.get(Person.class, tempOid);
tempTx.commit();
Full stack trace of any exception that occurs:Code:
1) testCreateOneToOne(mappings.one_to_one.TestOneToOneMapping)net.sf.hibernate.id.IdentifierGenerationException: null identifier generated
at net.sf.hibernate.impl.SessionImpl.saveWithGeneratedIdentifier(SessionImpl.java:762)
at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:731)
at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1380)
at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:114)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:436)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:503)
at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:883)
at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:850)
at net.sf.hibernate.impl.SessionImpl.saveWithGeneratedIdentifier(SessionImpl.java:768)
at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:731)
at mappings.one_to_one.TestOneToOneMapping.testCreateOneToOne(TestOneToOneMapping.java:69)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at mappings.one_to_one.TestOneToOneMapping.main(TestOneToOneMapping.java:21)
Name and version of the database you are using: mysql-4.0.20d-win
The generated SQL (show_sql=true): Code:
Hibernate: select person0_.PERSON_SEQ_NO as PERSON_S1_, person0_.FIRST_NAME as FIRST_NAME, person0_.LAST_NAME as LAST_NAME, person0_.MIDDLE_NAME as MIDDLE_N4_ from PERSON person0_
Debug level Hibernate log excerpt: