Hibernate exception - attempted to assign id from null one-to-one property
This was a tricky one to solve! Tricky because the exception doesn't happen at the point of error - it happens down the line at the time you try to commit a transaction. This is one of those error messages you just need to know. Here is the top of the exception's stack trace. Almost all of the rest of the stack trace is inside hibernate and doesn't give you any kind of clue as to the cause.
org.springframework.orm.hibernate3.HibernateSystemException: attempted to assign id from null one-to-one property: clip; nested exception is org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: clip
The error message we are concerned with is:
attempted to assign id from null one-to-one property: clip
Where clip
is the name of property. The exception is caused by trying to save a cascading object, without persisting the entity your object is referring to.
In my case I have the classes: Clip and Aaf. A Clip has one Aaf, so I need a one-to-one relationship. My Aaf object contains a blob but unfortunately hibernate doesn't let you do lazy initialisations on one-to-one relationships, so I've had to use a Set even though there is only ever one entry.
The situation is made slightly more complicated by the fact that I'm using a UUID as my primary key. Hibernate doesn't currently support UUID so I need a custom type along with a custom key generator.
[codeblock lang="xml" line="1"]
class="foreign"> clip
[/codeblock]
The Aaf's hibernate("hbm") file above says to use a uuid
identifier that is generated from the primary key of the clip
property. So if we look at the Aaf class you can see that the clip
property has type clip
[codeblock lang="Java" line="1"] public class Aaf { private UUID id; private Clip clip; } [/codeblock]
As you can see above id
is the record identifier but clip
(mentioned in the exception) is the relationship object that is used to set the record identifier. That is id
is never explicitly set by us, we set the clip property.
The first example is wrong.
[codeblock lang="Java" line="1"] Aaf aaf = new Aaf(aafInputStream); aafs = new HashSet< aaf >(); aafs.add(aaf); clip.setAaf(aafs); [/codeblock]
I was expecting that saving the Clip would do a cascade save on the Aaf object, but is doesn't. We need the an intermediate step of persisting the Aaf object first. In order to do this we need to fill in all the details of the Aaf record.
[codeblock lang="Java" line="1"] Aaf aaf = new Aaf(aafInputStream); aaf.setClip(clip); aafManager.set(aaf); aafs = new HashSet< aaf >(); aafs.add(aaf); clip.setAaf(aafs); sc = new AafUpdateStatechange(); sc.setClipId(isaClip.getId()); remoteEventQueue.send(sc); [/codeblock]
[codeblock lang="xml" line="1"]
class="foreign"> clip
object, before saving the clip relationship.
1 comment
Comment from: Jesper [Visitor]
Form is loading...