-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: TransientObjectException error if parent is not lazy loaded
PostPosted: Thu Feb 11, 2010 8:29 am 
Newbie

Joined: Thu Feb 11, 2010 7:54 am
Posts: 5
Hi,
I am relative newbie to hibernate. I am getting a org.hibernate.TransientObjectException error when I delete a child object "scenario" and then ask the parent for a list of scenarios. I am able to recover fine and subsequently fetch child "scenario" objects. It just the sequence "delete child" "fetch children" that fails. Everything works fine if I don't lazy load the parent from the child. I don't want to have the fetch the parent separately. I tried some of the cascade options but they did not seem to work.
Any help would be greatly appreciated.

Steve
error:
SEVERE: findAll
org.hibernate.TransientObjectException: object references an unsaved transient instance -
save the transient instance before flushing: com.loadgeneral.model.Workspace
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:242)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:430)

java code
Code:
    // this fails if the parent object workspace is not lazy loaded.
    // This works if the the parent "workspace" is lazy loaded in the child object "scenario"
    // delete(childScenario);
    // findAll(workspace) ----> this throws org.hibernate.TransientObjectException
    public List findAll(Workspace workspace) {
        log.debug("finding all");
        try {
            begin();
            Query q = getSession()
                  .createQuery("from com.loadgeneral.model.Scenario s where s.instance = :instance and s.workspace = :workspace order by s.lastmodified desc");
            q.setParameter("instance", 0);
            q.setParameter("workspace", workspace);

            List results = q.list();
            commit();

            log.debug("find all successful, result size: " + results.size());
            return results;
        }
        catch (RuntimeException re) {
            log.error("findAll", re);
            throw re;
        }
        finally{
            close();
        }
    }

   // delete child object, this works fine
    public void delete(Integer id) {
        log.debug("delete Object instance");
        try {
            begin();
            Object instance = getSession()
                    .get(this.persistentClass, id);

            getSession().delete(instance);
            commit();
            log.debug("delete successful");
        }
        catch (RuntimeException re) {
            rollback();
            log.error("delete failed", re);
            throw re;
        }
        finally{
            close();
        }
    }


Mappings
Code:
<hibernate-mapping>
    <class name="com.loadgeneral.model.Workspace" table="WORKSPACE">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="identity" />
        </id>

....
       <!-- children class -->
        <set name="scenarios" inverse="true" lazy="true" table="SCENARIO" fetch="select">
            <key>
                <column name="WORKSPACE_ID" not-null="true" />
            </key>
            <one-to-many class="com.loadgeneral.model.Scenario" />
        </set>
    </class>
</hibernate-mapping>

<hibernate-mapping>
    <class name="com.loadgeneral.model.Scenario" table="SCENARIO" select-before-update="true">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="identity" />
        </id>
        <!-- parent class                     -->
        <many-to-one name="workspace" class="com.loadgeneral.model.Workspace" update="false" lazy="false" fetch="select">
            <column name="WORKSPACE_ID" not-null="true" />
        </many-to-one>
..
</hibernate-mapping>


Top
 Profile  
 
 Post subject: Re: TransientObjectException error if parent is not lazy loaded
PostPosted: Thu Feb 11, 2010 12:12 pm 
Newbie

Joined: Thu Feb 11, 2010 7:54 am
Posts: 5
I think I have a better understanding and more questions.
1) What is the best way to delete a child object whose parent is not lazy loaded?
2) How should I notify the parent that a child has been deleted?
I tried cascade="delete" on the many-to-one setting.
3) Why should I get a TransientObjectException if I am committing and closing a session?

It seems like the following works fine if the parent is not lazy loaded.
Code:
    public void delete(Integer id) {
        log.debug("delete Object instance");
        try {
            begin();
            Object instance = getSession()
                    .load(this.persistentClass, id);

            getSession().delete(instance);
            commit();
            log.debug("delete successful");
        }
        catch (RuntimeException re) {
            rollback();
            log.error("delete failed", re);
            throw re;
        }
        finally{
            close();
        }
    }


Top
 Profile  
 
 Post subject: Re: TransientObjectException error if parent is not lazy loaded
PostPosted: Thu Feb 11, 2010 1:13 pm 
Senior
Senior

Joined: Mon Jul 07, 2008 4:35 pm
Posts: 141
Location: Berlin
Hi spince,

if you simply delete the entity instance in the database but not remove it from the collection in your parent instance it is still present, i.e. it is referenced by the parent instance. As long as you do not cascade a save from the parent to its children you will get this exception. (Note, cascading the save does not solve your problem)

You should approach this issue differently. Load your parent, remove the child you want to delete from the parent's children collection and then save the new state of the parent to the database. Before this will work as expected you should adapt your many-to-one mapping to use delete-orphan in your cascade attribute (possibly additionally to other values). You probably want to check the Transitive Persistence section in the Hibernate docs.

CU
Froestel

btw: Try to think more from an OO point of view than from a DB point of view. It helps a lot. For example, I don't think that wrapping Session.delete(Object) in a custom delete(Integer) makes very much sense. If you use surrogate keys as PKs your application does not need to take care of these. The keys are a database thingy, in Java you can work with object references.

_________________
Have you tried turning it off and on again? [Roy]


Top
 Profile  
 
 Post subject: Re: TransientObjectException error if parent is not lazy loaded
PostPosted: Thu Feb 11, 2010 2:32 pm 
Newbie

Joined: Thu Feb 11, 2010 7:54 am
Posts: 5
Froestel,
Thx for your reply. I think I have a better understanding on what is going. What you are saying makes sense. If the parent is loaded in the session(lazy == false) then the only way to delete a child is from it's parent. When you commit a transaction the parent is being updated and I still have a phantom reference to the child.


Steve


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.