The New Map Chaining Constructors and creating Creation Methods
Nov 05

Watch out for Hibernate unsaved-value

Tech Add comments

I spent far too much time on a stupid bug of my making.

Part of my model had a simple One to Many relationship.

Everything was fine until when creating a new child in the many side of the house I would see an error:

org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance – save the transient instance before flushing: model.Item

Why was it showing this from time to time?

I studied my Hibernate mapping files. I was using an inverse=”true” relationship, and the cascade options looked good.

Next, I checked over the code, and all seemed well.

It turned out that I had set the unsaved value in a past life:

<id name=”id” column=”id” unsaved-value=”0″>

The problem was occuring ONLY on a parent with the id of 0!

Duh!

What I would give for top class error messages when writing apps.

“Hey you idiot. You have set the unsaved-value to 0. Think that may be the problem?”

:)

23 Responses to “Watch out for Hibernate unsaved-value”

  1. dmad Says:

    Thats really bad luck! :) I thought of that mistake the first time I saw the unsaved-property. Since that I know to use Objects as Identifiers (e.g. Long instead of long) ;-)

    btw: I had problems with the bags cause there is no word of using List-Objects instead of Set :(

    GreetingZ
    dancingmad

  2. Cyril Says:

    Hello, are you sure the error came from the :
    unsaved-value=”0″?(or is there something (more) else?)
    because I don’t have such expressions in my code but the same error : org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance – save the transient instance before flushing: com.osa.mdsp.csp.mdspconf.model.NotificationVersion
    and I just don’t know what to do…
    Thanks,

    Cyril

  3. Anonymous Says:

    zxc

  4. meriu Says:

    cyril,
    i had the same problem – try set cascade parameter to “all”; i resolved it by setting
    in hbm.xml mapping file;

  5. meriu Says:

    stupid system – it ate my solution:

    &lthibernate-mapping default-cascade=”all”&gt

  6. Luigi Says:

    Thanks very much for your advice!
    I had unsaved-value=”0″, and a row in the database had an id=0, and i got the same error…

    Bye,
    Luigi

  7. Patrick Farrell Says:

    Totally agree with you on better error messages. I’ve worked 2 big projects with Hibernate and Spring. Those frameworks are awesome to maintain, but not nearly descriptive enough with many of their errors. Probably will come with maturity.

    PF

    ps: (I wanted to say blogging-script, but that would just be bs: ;) How bout hookin’ up the CAPTCHA to validate a user’s session instead of requiring a validation on every post?

  8. jagan Says:

    when i am passing parent obj. to the hibernate to persist the data, i am getting the exception as mentioned below…
    exception raised when calling Hibernate Objectnet.sf.hibernate.HibernateException: The given object has a null identifier property

  9. Henrik Says:

    Thank you very plenty Dion!

    I was as stuck as you when i found your blog, couldn’t grip any of the error messages.

    Thanks for taking the effort of blogging it out.

    Regards
    /Henrik

  10. ARIS Says:

    hi i was wondering when cyril had the problem you said to change the cascade parameter to all in the hbm.xml file, but where do find that file? i dont even have one.. but the only thing not working is mapping the list using hibernate

  11. nour Says:

    i have the same error but not the same case ,i have class related in other one by foreign key, and i may have null relation that means there is no row in main class.is there any body can help me what could i do???

  12. PaulBurns Says:

    I had the same error but the problem was different. I was attempting to insert limited sample data so that every time I re-created the schema I could have a few details to use.

    Offending code was in my GlobalApplication file, just after I had created the schema;

    User user1 = new User();
    user1.UserName = “Pete”;
    user1.Name = “Peter”;
    user1.Surname = “Smith”;
    user1.Email = “[email protected]”;
    user1.Password = “password”;
    user1.Active = true;
    user1.Create();

    Page page1 = new Page();
    page1.Content = “1″;
    page1.PageTitle = “1″;
    page1.PageUpdatedBy = user1;
    page1.Publish = true;
    page1.Snippet = “1″;
    page1.DateCreated = DateTime.Now;
    page1.DateUpdated = DateTime.Now;
    page1.MetaDescription = “1″;
    page1.MetaTags = “1″;
    page1.MetaTitle = “1″;
    page1.Create();

    The problem was with referencing user1 before the instance is saved. Dunno if it will help anyone but worth noting!

  13. someone Says:

    +1 thanks :-)

  14. aspier Says:

    oh my god!
    I also can not slove the problem?
    other reasons?
    help!

  15. Damon Murfitt Says:

    Hi, thought i would throw my thoughts at this discussion. hopefully i’ll be helpfull.

    I had this problem and it was related to my IInterceptor implementation.

    I used a base Persister class to give nHibernate a hint to determine if a class was already in the DB.

    As i was developing a web app there were occasions where i had to manually create an object using an ID. i.e Person myPerson = new Person(17765);

    I then added this Person to a collection of Another object. When attempting to persist this object nHibernate checked myPerson.IsSaved which was false because i hadn’t actually loaded this object from nhibernate. Because it was false nHibernate assumed it was unsaved so threw the exception being discussed (after all it didn’t want to go and attempt to create an insert in my join table using the primary key of an object that didn’t exists in the database).

    Anyhows, changing my code to this resolved the error:
    Person myPerson = new Person(17765)
    myPerson.IsSaved = true;

    Please note that i new a person with id 17765 already existed but i didn’t want to keep going to the DB everytime i added a person to the collection. (Going to the db and getting the person would also have prevented the error. i.e myPerson = session.Get(17765); because hnibernate knows it exist in the db when i comes to save the association)

    Now…Another scenario where you could get this exception would be:

    I create a new Person who does not have a record in my DB:
    Person myPerson = new Person(99999);
    myPerson.IsSaved = false;
    If I then add this person to the collection of my other object, lets call it “Bus”….so….
    Bus.Passengers.Add(myPerson)

    When nhibernate attempts to save Bus if i don’t have cascade=”save-update” set in Bus.hbl.xml file then once again nhibernate will not want to insert into the join table using a myPerson.Id which does not exist in the Person database table.

    Alternatively if i don’t want to set cascade in Bus.hbl.xml then i must explicitly save myPerson so that the record does exist before nhibernate goes to insert that join record.

    Phew. Rambled a bit there, hope it helps someone.

  16. Laura Says:

    I encountered your site several times when I was looking for a way to fix my problem, but since i had no unsaved-value in my hibernate files, i did not think that was the problem.

    However, the fact that I had no unsaved-value was the problem, because Hibernate believes that “0″ is an unsaved-value by default. Took me a whole day to realize this and put a “unsaved-value=-1″ in the mapping.

  17. zubair Says:

    I had this problem. I solved it by the inverse=”true” on the parent.
    I left the unsaved value= 0 and no issues with that.
    Parent is a one to many to the child and the child was a many to one.
    Defined it in the hbml files.
    If u unsaved value is or -1 or even 1 u can get stale exceptions.

  18. Ray Says:

    I was getting the same error. I had a persistent parent with a transient child causing the error. I added a cascade=”all” attribute to the many-to-one mapping, and presto it’s fixed.

  19. Raja Nagendra Kumar Says:

    Hi zubair ,

    Could pl. let me know how to set inverse attribute using annotations. I read inverse equivalent is mappedby.. however for a cose like this..

    Map where DateTimeSpec is create and not saved yet but added to this map. When the class having this map instance is saved I am expecting all the new one referenced in the map of DateTimeSpec, AbstractTezzD should be saved. Also, pl. observe that map holder is also a class which is part of inhericance chain for value of the map..

    public final class TimeTezzD extends AbstractTezzD
    {
    @OneToMany(fetch = FetchType.EAGER,
    cascade = CascadeType.ALL)
    @JoinTable(name = “tbl_time_tezzds_map”,
    joinColumns = {@JoinColumn(name = “fk_time_tezzds”,
    nullable = false)},
    inverseJoinColumns = {@JoinColumn(name = “fk_abs_tezzds”,
    nullable = false)})
    private final Map timeTezzDMap = new HashMap();

    ..

    Workaround I see is this..

    Every DataTimeSpec object I added I save it first and then add to this map. then it is working.. however looking for jpa system to auto take care of it.. rather than giving the

    [java] There was 1 error:
    [java] 1) testValid(com.tejasoft.dialer.model.bdo.tns.time.test.TestTimeTez
    zD)org.hibernate.TransientObjectException: object references an unsaved transien
    t instance – save the transient instance before flushing: com.tejasoft.dialer.mo
    del.bdo.tns.time.DateTimeSpec

    Any clues would help..

    Regards,
    Raja Nagendra Kumar,
    C.T.O
    http://www.tejasoft.com

  20. Meidan Says:

    Dude! You’ve probably saved me tons of debugging time after deploying to production where the was an entity with id = 0.
    Thanks!

  21. Abhinav Says:

    Thanks..this post saved a lot of my debugging time…

  22. John Thompson Says:

    I got a “references an unsaved transient instance” error when trying to create instances of a one to many relationship. The problem was that I created all the objects and related them to each other on both sides of the one-to-many in code, but then I tried session.Save on the many side object. I guess this caused the error because it was unable to store the many side record because it had not stored the one side record yet, and therefore, it did not know the prime key value to use for the many side foreign key. Thus the error complains about an “unsaved (transient) instance”.
    This is all a bit wordy and may not seem important, but it does cause a problem. I got the error when trying to save a Customer entity, that was related to a default address. I wanted to save the objects from the customer point of view because that is what drives the data structure from the business point of view. However, I was forced to save the customer by saving the address, and letting that cause the customer to save once the address was saved and the address key was known.
    This worries me, however, because I have not been using nHibernate for long, but it looks like certain object graphs that include both one-to-many and many-to-one relations may not be saveable by nHibernate.
    I don’t know if this makes any sense without me showing loads of code samples and diagrams, but I would like to know if anyone has had any similar issues or concerns.

  23. Daryl Teo Says:

    Mate, you just saved me half a day of frustration! THANK YOU

Leave a Reply

Spam is a pain, I am sorry to have to do this to you, but can you answer the question below?

Q: Type in the word 'ajax'