-->
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.  [ 7 posts ] 
Author Message
 Post subject: update never occurs when using an Interceptor
PostPosted: Mon Jan 19, 2004 5:54 am 
Newbie

Joined: Tue Dec 16, 2003 9:57 am
Posts: 13
Hi,
I'm using Hibernate 2.1.1, Windows 2000, Jdk 1.3 and DB2 7.2. I'm having trouble with a parent-child relationship, as explained in this thread (
http://forum.hibernate.org/viewtopic.php?t=927180).

I'm trying to implement my Involved object as a Persistent class - following the Hibernate documentation chapter 9.4 (http://www.hibernate.org/hib_docs/reference/html/parent-child.html#parent-child-update). I've also implemented an Interceptor as shown in the same chapter:

Code:
public class MyInterceptor implements Interceptor{
public boolean onLoad(
  Object entity,
  Serializable id,
  Object[] state,
  String[] propertyNames,
  Type[] types)
  throws CallbackException
{
  if (entity instanceof Persistent) {
    ((Persistent) entity).onLoad();
  }
  return false;
}

public boolean onSave(
  Object entity,
  Serializable id,
  Object[] state,
  String[] propertyNames,
  Type[] types)
  throws CallbackException
{
  if (entity instanceof Persistent) {
    ((Persistent) entity).onSave();
  }
  return false;
}


public Boolean isUnsaved(Object entity) {
  if (entity instanceof Persistent) {
    return new Boolean(!((Persistent) entity).isSaved());
  } else {
    return null;
  }
}

public boolean onFlushDirty(
  Object entity,
  Serializable id,
  Object[] currentState,
  Object[] previousState,
  String[] propertyNames,
  Type[] types)
  throws CallbackException
{
  return false;
}

public void onDelete(
  Object entity,
  Serializable id,
  Object[] state,
  String[] propertyNames,
  Type[] types)
  throws CallbackException
{
}

public void preFlush(Iterator entities) throws CallbackException {
}

public void postFlush(Iterator entities) throws CallbackException {
}

public int[] findDirty(
  Object entity,
  Serializable id,
  Object[] currentState,
  Object[] previousState,
  String[] propertyNames,
  Type[] types)
{
  return new int[0];
}

public Object instantiate(Class clazz, Serializable id) throws CallbackException {
  return null;
}
}



Then I try this:

Code:
session = SessionFactoryPlant.getSessionFactory().openSession( new MyInterceptor());
tx = session.beginTransaction();

if( case.getId() != null ){ // this is an update!
  persistedCase = (Case) session.get( Case.class, case.getId() );
  copyForPersistence(persistedCase, case);
  session.flush();
} else {
  copyForPersistence(persistedCase, case);
  session.save( persistedCase );
}
tx.commit();
session.close;


Only the Involved class extends the Persistent class. When I run the code, the saving works fine (new instance). The correct insert statement is invoked and I'm a happy fellow. When I try to update an existing case, no update statement is invoked.

The copyForPersistence method copies all attributes from the case object (which I got from the web layer) to the persistedCase object (which in this case is retrieved from the database).

Why isn't an update invoked when I change a persisted object and invoke commit()?

Thanks for all help!

Regards,
Ola


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 19, 2004 6:08 am 
Newbie

Joined: Tue Dec 16, 2003 9:57 am
Posts: 13
I found one error, the findDirty method should return null - not an empty array - to use Hibernate's default dirty-checking algorithm:

Code:
public int[] findDirty(
  Object entity,
  Serializable id,
  Object[] currentState,
  Object[] previousState,
  String[] propertyNames,
  Type[] types)
{
  return null;
}


I'm one step closer to Nirvana ;)

Regards,
Ola


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 19, 2004 6:36 am 
Newbie

Joined: Tue Dec 16, 2003 9:57 am
Posts: 13
Two steps forward, and one back. Now I get the following error when trying to update:

Code:
net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [id]=23057912234, [caseId]=379, of class: Involved
at net.sf.hibernate.impl.SessionImpl.checkUniqueness(SessionImpl.java:1605)
at net.sf.hibernate.impl.SessionImpl.doUpdateMutable(SessionImpl.java:1377)
at net.sf.hibernate.impl.SessionImpl.doUpdate(SessionImpl.java:1403)
at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1338)
at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:114)


Yes, it exist - but I want to update it. Tracing the code reveals that the Interceptor returns the correct value for isUnsaved() - false. Shouldn't this result in an update call to the db/session? Here's what I do in an update:

1. Get new Case object from web layer
2. If id != null, get persistedCase from db
3. Copy all attributes from case to persistedCase
3a. The involved set is cleared (case.getInvolved().clear())
3b. Involved objects are added from case (with saved=true)
4. transaction committed

Regards,
Ola


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 19, 2004 6:47 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Basicaly, you update() (means attach to the session for update) an object that was already attached to the session (previous load in this session ?). These are the same persistent representation (same id/type) but with different instances. You cannot do that.
Either evict() the object before update() it or use the already associated instance by loading it.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 19, 2004 7:34 am 
Newbie

Joined: Tue Dec 16, 2003 9:57 am
Posts: 13
Thanks for the quick response Emmanuel!

However, I've changed my code to the code below, but still get the same exception:
Code:
Session session = null;
Transaction tx = null;
Case persistedCase = new Case();
try {
  session = SessionFactoryPlant.getSessionFactory().openSession( new MyInterceptor());
  tx = session.beginTransaction();
  if( case.getId() != null ){
    // Update existing instance
    session.load( persistedCase, case.getId() );
    copyForPersistence(persistedCase, case);
  } else {
    // New instance
    copyForPersistence(persistedCase, case);
    session.save( persistedCase );
  }
  tx.commit();
  session.close();
} catch ...


How can I retrieve an instance of Case, change some of the attributes (also the Involved set), and save it? That's what I'm trying to do. I thought the commit-call would persist the changes to the database...?

Regards,
Ola
[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 19, 2004 7:40 am 
Newbie

Joined: Tue Dec 16, 2003 9:57 am
Posts: 13
To follow up myself:

The code which handles the Involved set is like this:

Code:
copyTo.getInvolved().clear();
Iterator itr = copyFrom.getInvolved().iterator();
while (itr.hasNext()) {
  copyTo.addInvolved((Involved) itr.next());
}


Is it the clear-statement which messes things up? It clears the set, but the Involved object is still in the session cache? And then, when I try to add new Involved, the exception occurs...

Hmm... I think I gettit now.

- Ola


Top
 Profile  
 
 Post subject: related problem?
PostPosted: Mon Jan 19, 2004 4:14 pm 
Beginner
Beginner

Joined: Fri Jan 16, 2004 3:22 pm
Posts: 26
hello everybody,

i'm also experiencing some problems with NonUniqueObjectException.
The app is about users, messages and topics. the relations between classes are:
(owns) user 1:n topic
(memberof) user n:n topic
(author) user 1:n message
(belong) message n:1 topic


the problem ocurrs when trying to save a new message (i'm using springframework's HibernateDaoSupport):

Code:
getHibernateTemplate().save(object);


given that spring handles the session i'm pretty sure i could not have loaded a previos object in there, moreover, setting on the debug level of the logger i can see how a new session is been created before the exception raises:

Code:
DEBUG SessionImpl:528 - opened session
DEBUG BatcherImpl:192 - about to open: 0 open PreparedStatements, 0 open ResultSets
DEBUG SQL:223 - select nextval ('hibernate_sequence')
    ...
DEBUG SessionImpl:786 - saving [Message#5]
DEBUG Cascades:497 - processing cascades for: Message
    ...
DEBUG SessionImpl:546 - closing session
    ...
org.springframework.orm.hibernate.HibernateSystemException: a different object
the same identifier value was already associated with the session: 1, of class: User; nested exception is:
        net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 1, of class: User


with so little code written is it possible to be related to some ill declared relation in the hbm.xml ???

any help would be deeply appreciated


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.