-->
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.  [ 8 posts ] 
Author Message
 Post subject: Save the transient instance before flushing
PostPosted: Fri Feb 20, 2009 6:39 am 
Beginner
Beginner

Joined: Thu Feb 19, 2009 5:48 am
Posts: 37
Location: Glasgow, Scotland
I've had a look to see if anyone has came across this problem before and indeed they have, it seems everyones problem was fixed with the addition of cascade="save-update" though, this is not the case with mine.
Thanks in advance for any help :D

Hibernate version:3.2.6

Mapping documents:
Code:
<hibernate-mapping>
    <class name="Event" table="EVENTS">
        <id name="id" column="EVENT_ID" unsaved-value="-1">
            <generator class="native"/>
        </id>
       
        <property name="date" type="timestamp" column="EVENT_DATE"/>
        <property name="title"/>
       
      <set name="clients" table="CLIENTS" cascade="save-update">
         <key column="id" />
         <one-to-many class="Client"  />
      </set>
      
        <property name="requiredResources" type="ResourcesUserType" column="resourceNames" />
    </class>

    <class name="Client" table="Client">
        <id name="id" column="CLIENT_ID" unsaved-value="-1">
            <generator class="native"/>
        </id>
        <property name="name"/>
    </class>

    <class name="Resource" table="Resource">
        <id name="id" column="RESOURCE_ID" unsaved-value="-1">
            <generator class="native"/>
        </id>
        <property name="name"/>
    </class>
</hibernate-mapping>



Code between sessionFactory.openSession() and session.close():
Code:
    private void createAndStoreEvent(String title, Date theDate, List<Client> clients, List<Resource> resources) {

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Event theEvent = new Event();
         theEvent.setTitle(title);
         theEvent.setDate(theDate);
         theEvent.setClients(clients);
         theEvent.setRequiredResources(resources);

        session.save(theEvent);

        session.getTransaction().commit();
    }


Full stack trace of any exception that occurs:
Code:
578 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Client
   at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:242)
   at org.hibernate.type.EntityType.getIdentifier(EntityType.java:430)
   at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:101)
   at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:777)
   at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1165)
   at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:171)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
   at EventManager.createAndStoreEvent(EventManager.java:61)
   at EventManager.main(EventManager.java:29)
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Client
   at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:242)
   at org.hibernate.type.EntityType.getIdentifier(EntityType.java:430)
   at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:101)
   at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:777)
   at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1165)
   at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:171)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
   at EventManager.createAndStoreEvent(EventManager.java:61)
   at EventManager.main(EventManager.java:29)



Name and version of the database you are using:PostGres

The generated SQL (show_sql=true):
Code:
Hibernate: insert into EVENTS (EVENT_ID, EVENT_DATE, title, resourceNames) values (null, ?, ?, ?)
org.hsqldb.jdbc.jdbcPreparedStatement@adb1d4[sql=[insert into EVENTS (EVENT_ID, EVENT_DATE, title, resourceNames) values (null, ?, ?, ?)], parameters=[[2009-02-20 10:36:15.587], [StoreTest], [null]]]
Hibernate: call identity()
Hibernate: update Client set id=? where CLIENT_ID=?

[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 7:08 am 
Beginner
Beginner

Joined: Thu Jun 12, 2008 10:48 am
Posts: 24
Do you not need a set of resources in the same way you have a set of clients in your mapping file?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 7:12 am 
Beginner
Beginner

Joined: Thu Feb 19, 2009 5:48 am
Posts: 37
Location: Glasgow, Scotland
I see what you mean but no, it's a legacy database in which there is one field which holds a list of Resource names which are then split and individually retrieved from the Resource table, awkward I know but apparently the idea was to cut down JOINs.

The problem I'm having though seems to be with the Client association.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 8:31 am 
Newbie

Joined: Fri Feb 20, 2009 8:03 am
Posts: 3
Location: India
Can you kindly change id in key tag to event id as it shown below,

<set name="clients" table="CLIENTS" cascade="save-update">
<key column="EVENT_ID" />
<one-to-many class="Client" />
</set>

_________________
Jansi.P


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 9:09 am 
Expert
Expert

Joined: Fri Jan 30, 2009 1:47 am
Posts: 292
Location: Bangalore, India
jansi wrote:
Can you kindly change id in key tag to event id

No I dont think this is the issue here. The key tag should have value "id" if that is the foriegnkey column name or "event_id" if thats the foreign key column name.

But the issue is with your unsaved-value="-1" attribute. You have specified that the unsaved-value is -1. But assuming that the id properties are long or int, whenever you create a Event or Client object the id property will get initialized to 0. So when you are saving this object Hibernate will see that the id field is 0 != -1; so it assumes that the object you provide is a transient object having a corresponding row in the DB with primary key 0. So it will just issue an update for the Client object and not an insert.

So if you put unsaved-value="0" in the mapping then it should work fine. Or you initialize your POJO id fields with -1.

_________________
Regards,
Litty Preeth


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 9:12 am 
Beginner
Beginner

Joined: Thu Feb 19, 2009 5:48 am
Posts: 37
Location: Glasgow, Scotland
Ok, turns out that my problem was the hbm.xml files weren't being accessed by the .class files properly, not a Hibernate problem at all.
But thanks for the EVENT_ID. I never even noticed that I'd did that

_________________
##############################
If I helped, rate my comment, I have plenty of stupid questions to ask that I need credit for ;)
##############################


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 9:18 am 
Beginner
Beginner

Joined: Thu Feb 19, 2009 5:48 am
Posts: 37
Location: Glasgow, Scotland
littypreethkr wrote:
So if you put unsaved-value="0" in the mapping then it should work fine. Or you initialize your POJO id fields with -1.


As I said, the issue was with my project directories rather than hibernate. Useful information though thanks

_________________
##############################
If I helped, rate my comment, I have plenty of stupid questions to ask that I need credit for ;)
##############################


Top
 Profile  
 
 Post subject: Re: Save the transient instance before flushing
PostPosted: Tue Jan 26, 2010 4:35 am 
Newbie

Joined: Thu Aug 20, 2009 3:00 am
Posts: 11
I had this message "org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing com.vetmanager.database.animal.Animal" from this pease of code:
Code:
      
if((consult==null || consult.getId()==null) && animal!=null) {
  // select newest consult for this an animal
  EntityManager entityManager = getEntityManagerFactory().createEntityManager();
  Query query = entityManager.createQuery("FROM Consult WHERE animal = :animal ORDER BY consultDate DESC");
  query.setParameter("animal", animal);
  ArrayList<Consult> consults = (ArrayList<Consult>)query.getResultList();                  <=== Line where the exception was raised
  if(consults.size()>0) {
    setConsult(consults.get(0));
  }
    entityManager.close();
  }
}


But animal is just a new object and completely empty. It seams that Hibernate/Persistence checks if the id==null. If so it desides that the object must be transient. So changing the code slightly fixed it:
Code:
if((consult==null || consult.getId()==null) && animal!=null && animal.getId()!=null) {
...


So in my case it had nothing to do with database issues but just with that I used an empty object without a valid id.

Hope this helps anybody :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 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:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.