Quote:
If I change the many-to-one mapping in Hand to have not-null="false", then the error goes away. Smells to me like the objects are being persisted out of order. The code I'm using calls Session.save() on the person object, and I would assume the cascade setting would take care of everything.
Setting not-null="false" doesn't really work, because you'll find that the value in the "person_id" column of the "Hand" table will *always* end up null.
The problem you're seeing is that the two related <many-to-one> elements are effectively 2 Foreign Keys referencing each other. If you put not-null FK constraints on these columns, you could never insert the Person-Hand data you want, because you'd always get a FK violation due to a missing row in the related table (no matter which order you attempted the insert).
For a more exact explanation of the behaviour you're seeing: in order to avoid FK constraints, Hibernate nullifies the "unsaved" Person reference of your Hand object prior to insertion, in this code (SessionImpl.java:874):
Code:
TypeFactory.deepCopy(values, types, persister.getPropertyUpdateability(), values);
nullifyTransientReferences(values, types, useIdentityColumn, object);
checkNullability(values, persister, false);
If Hibernate knows that the Person should be "not-null", then the checkNullability fails. If not, the Hand will be created with a null value for person_id. Neither is really what you want, methinks.
To be honest, I can't see an easy way to do what you want. You're effectively asking Hibernate to maintain a redundant column (the person_id column of the Hand table) in order to preserve uniqueness in the Hand-Person relationship, and provide a bidirectional relationship. You could treat Hand.getPersonId() as a simple property, and make sure it is set in code, but you still won't be able to call Hand.getPerson() on a newly loaded instance.
Maybe someone smarter than me can help out with this :)