-->
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.  [ 5 posts ] 
Author Message
 Post subject: Changing saveOrUpdate() to merge() results in exception
PostPosted: Wed Feb 14, 2007 3:43 am 
Newbie

Joined: Wed Feb 14, 2007 2:51 am
Posts: 5
Hi all,

I've got an app with quite deep object graph structure. I'm working with rich client using Spring remoting, so I work a lot with detached objects. I dealed with some NonUniqueObjectExceptions so I tried to use merge() instead of saveOrUpdate() in my DAOs. But now, it throws NullPointerException.

A part of my code was OK with saveOrUpdate(), but another was causing NonUniqueObjectException and due to I use a generic DAO save method which is common for all my DAOs, I simply changed one line of my code to use merge(). After that the NonUniqueObjectException has gone but in another part of the system the NullPointerException is trown. My conf as well as the stack trace follow.

Unfortunatelly I think that I am not able to provide some simple example, because the object graph is quite complex and in fact I don't know where to search for a possible mistake. It seems to me that it may be some bug in Hibernate becase the use case throwing exception with merge() was fine with saveOrUpdate().
Can anybody help me?

I use:
Hibernate 3.2.2, Hibernate Annotations 3.2.1, Spring 2.0.1, MySQL 5.0.27, Java 5 - update 10.

The thrown exception stack trace:

Code:
java.lang.NullPointerException
   at org.hibernate.engine.StatefulPersistenceContext.proxyFor(StatefulPersistenceContext.java:657)
   at org.hibernate.type.ComponentType.instantiate(ComponentType.java:492)
   at org.hibernate.type.ComponentType.replace(ComponentType.java:459)
   at org.hibernate.type.TypeFactory.replace(TypeFactory.java:495)
   at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:377)
   at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:179)
   at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
   at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687)
   at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669)
   at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245)
   at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
   at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
   at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
   at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
   at org.hibernate.event.def.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:407)
   at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:266)
   at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120)
   at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687)
   at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669)
   at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245)
   at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
   at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
   at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
   at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
   at org.hibernate.event.def.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:407)
   at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:266)
   at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120)
   at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
   at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
   at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
   at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
   at org.springframework.orm.hibernate3.HibernateTemplate$23.doInHibernate(HibernateTemplate.java:755)
   at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:362)
   at org.springframework.orm.hibernate3.HibernateTemplate.merge(HibernateTemplate.java:752)
...


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 14, 2007 12:11 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
saveOrUpdate does not have the same functionality as merge.

If you merge() a transient object and it has no identity set (b/c it is getting autogenerated by the database), the object that was merged will still not have an id after the merge() operation. But with saveOrUpdate(), it will.

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


Top
 Profile  
 
 Post subject: Some info from logs
PostPosted: Wed Feb 14, 2007 12:22 pm 
Newbie

Joined: Wed Feb 14, 2007 2:51 am
Posts: 5
OK, i've done some debugging. Here is the info from the log file.

The model is like this:
Code:
package model;

class TopClass {
   
    @OneToMany(mappedBy="top",cascade=CascadeType.ALL)
    Set<ClassA> listOfClassA;

}

class ClassA {

    @ManyToOne
    TopClass top;
   
    @OneToMany(mappedBy="classA",cascade=CascadeType.ALL)
    Set<ClassB> listOfClassB;
}

class ClassB {

    @ManyToOne
    ClassA classA;
   
}



In my use case I have an detached instance of TopClass. I add some new (transient) ClassA instancies and to ech of them some new ClassB instancies.

Then I do
Code:
session.saveOrUpdate(topClassInstance)
or
Code:
session.merge(topClassInstance)


log contents for saveOrUpdate():

Code:
2007-02-14 11:30:06,546 DEBUG [org.hibernate.engine.CascadingAction] - cascading to saveOrUpdate: model.ClassA
2007-02-14 11:30:06,546 DEBUG [org.hibernate.engine.VersionValue] - version unsaved-value strategy UNDEFINED
2007-02-14 11:30:06,546 DEBUG [org.hibernate.engine.IdentifierValue] - id unsaved-value: 0
2007-02-14 11:30:06,546 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - transient instance of: model.ClassA
2007-02-14 11:30:06,546 DEBUG [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] - saving transient instance
2007-02-14 11:30:06,546 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - saving [model.ClassA#<null>]
2007-02-14 11:30:06,546 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - executing insertions
2007-02-14 11:30:06,546 DEBUG [org.hibernate.engine.Cascade] - processing cascade ACTION_SAVE_UPDATE for: model.ClassA
2007-02-14 11:30:06,546 DEBUG [org.hibernate.engine.Cascade] - done processing cascade ACTION_SAVE_UPDATE for: model.ClassA
2007-02-14 11:30:06,546 DEBUG [org.hibernate.engine.Versioning] - using initial version: 0
2007-02-14 11:30:06,546 DEBUG [org.hibernate.engine.IdentifierValue] - id unsaved-value: 0
2007-02-14 11:30:06,546 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - executing identity-insert immediately
2007-02-14 11:30:06,546 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Inserting entity: model.ClassA (native id)
2007-02-14 11:30:06,546 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Version: 0
2007-02-14 11:30:06,546 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2007-02-14 11:30:06,546 DEBUG [org.hibernate.SQL] - insert into ... // omitted
2007-02-14 11:30:06,546 DEBUG [org.hibernate.jdbc.AbstractBatcher] - preparing statement
2007-02-14 11:30:06,562 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Dehydrating entity: [model.ClassA#<null>]
2007-02-14 11:30:06,562 DEBUG [org.hibernate.id.IdentifierGeneratorFactory] - Natively generated identity: 12
2007-02-14 11:30:06,562 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2007-02-14 11:30:06,562 DEBUG [org.hibernate.jdbc.AbstractBatcher] - closing statement
2007-02-14 11:30:06,562 DEBUG [org.hibernate.engine.Cascade] - processing cascade ACTION_SAVE_UPDATE for: model.ClassA
2007-02-14 11:30:06,562 DEBUG [org.hibernate.engine.Cascade] - cascade ACTION_SAVE_UPDATE for collection: model.ClassA.listOfClassB
2007-02-14 11:30:06,562 DEBUG [org.hibernate.engine.CascadingAction] - cascading to saveOrUpdate: model.ClassB
2007-02-14 11:30:06,562 DEBUG [org.hibernate.engine.VersionValue] - version unsaved-value strategy UNDEFINED
2007-02-14 11:30:06,562 DEBUG [org.hibernate.engine.IdentifierValue] - id unsaved-value: 0
2007-02-14 11:30:06,562 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - transient instance of: model.ClassB
2007-02-14 11:30:06,562 DEBUG [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] - saving transient instance
2007-02-14 11:30:06,562 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - saving [model.ClassB#<null>]
2007-02-14 11:30:06,562 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - executing insertions
2007-02-14 11:30:06,562 DEBUG [org.hibernate.engine.Cascade] - processing cascade ACTION_SAVE_UPDATE for: model.ClassB
2007-02-14 11:30:06,562 DEBUG [org.hibernate.engine.Cascade] - done processing cascade ACTION_SAVE_UPDATE for: model.ClassB
2007-02-14 11:30:06,562 DEBUG [org.hibernate.engine.Versioning] - using initial version: 0
2007-02-14 11:30:06,562 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - executing identity-insert immediately
2007-02-14 11:30:06,562 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Inserting entity: model.ClassB (native id)
...
...
continue OK


As you can see, everything works fine.

log contents for merge():

Code:
2007-02-14 11:17:05,656 DEBUG [org.hibernate.engine.CascadingAction] - cascading to merge: model.ClassA
2007-02-14 11:17:05,656 DEBUG [org.hibernate.engine.VersionValue] - version unsaved-value strategy UNDEFINED
2007-02-14 11:17:05,656 DEBUG [org.hibernate.engine.IdentifierValue] - id unsaved-value: 0
2007-02-14 11:17:05,656 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - transient instance of: model.ClassA
2007-02-14 11:17:05,656 DEBUG [org.hibernate.event.def.DefaultMergeEventListener] - merging transient instance
2007-02-14 11:17:05,656 DEBUG [org.hibernate.engine.Cascade] - processing cascade ACTION_MERGE for: model.ClassA
2007-02-14 11:17:05,656 DEBUG [org.hibernate.engine.Cascade] - done processing cascade ACTION_MERGE for: model.ClassA
2007-02-14 11:17:05,656 DEBUG [org.hibernate.engine.IdentifierValue] - id unsaved-value: 0
2007-02-14 11:17:05,656 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - saving [model.ClassA#<null>]
2007-02-14 11:17:05,656 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - executing insertions
2007-02-14 11:17:05,656 DEBUG [org.hibernate.engine.Versioning] - using initial version: 0
2007-02-14 11:17:05,671 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - executing identity-insert immediately
2007-02-14 11:17:05,671 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Inserting entity: model.ClassA (native id)
2007-02-14 11:17:05,671 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Version: 0
2007-02-14 11:17:05,671 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2007-02-14 11:17:05,671 DEBUG [org.hibernate.SQL] - insert into ..... // ommited
2007-02-14 11:17:05,671 DEBUG [org.hibernate.jdbc.AbstractBatcher] - preparing statement
2007-02-14 11:17:05,687 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Dehydrating entity: [model.ClassA#<null>]
2007-02-14 11:17:05,687 DEBUG [org.hibernate.id.IdentifierGeneratorFactory] - Natively generated identity: 11
2007-02-14 11:17:05,687 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2007-02-14 11:17:05,687 DEBUG [org.hibernate.jdbc.AbstractBatcher] - closing statement
2007-02-14 11:17:05,687 DEBUG [org.hibernate.engine.Cascade] - processing cascade ACTION_MERGE for: model.ClassA
2007-02-14 11:17:05,687 DEBUG [org.hibernate.engine.Cascade] - cascade ACTION_MERGE for collection: model.ClassA.listOfClassB
2007-02-14 11:17:05,687 DEBUG [org.hibernate.engine.CascadingAction] - cascading to merge: model.ClassB
2007-02-14 11:17:05,687 DEBUG [org.hibernate.engine.VersionValue] - version unsaved-value strategy UNDEFINED
2007-02-14 11:17:05,687 DEBUG [org.hibernate.engine.IdentifierValue] - id unsaved-value: 0
2007-02-14 11:17:05,687 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - transient instance of: model.ClassB
2007-02-14 11:17:05,687 DEBUG [org.hibernate.event.def.DefaultMergeEventListener] - merging transient instance
2007-02-14 11:17:05,687 DEBUG [org.hibernate.engine.Cascade] - processing cascade ACTION_MERGE for: model.ClassB
2007-02-14 11:17:05,687 DEBUG [org.hibernate.engine.Cascade] - done processing cascade ACTION_MERGE for: model.ClassB
2007-02-14 11:17:05,687 DEBUG [org.hibernate.transaction.JDBCTransaction] - rollback
2007-02-14 11:17:05,687 DEBUG [org.hibernate.transaction.JDBCTransaction] - re-enabling autocommit
2007-02-14 11:17:05,687 DEBUG [org.hibernate.transaction.JDBCTransaction] - rolled back JDBC Connection
2007-02-14 11:17:05,687 DEBUG [org.hibernate.jdbc.JDBCContext] - after transaction completion
2007-02-14 11:17:05,687 DEBUG [org.hibernate.jdbc.ConnectionManager] - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
2007-02-14 11:17:05,687 DEBUG [org.hibernate.impl.SessionImpl] - after transaction completion
2007-02-14 11:17:05,687 DEBUG [org.hibernate.impl.SessionImpl] - setting flush mode to: NEVER
2007-02-14 11:17:05,687 DEBUG [org.hibernate.impl.SessionImpl] - disconnecting session
2007-02-14 11:17:05,687 DEBUG [org.hibernate.jdbc.ConnectionManager] - performing cleanup
2007-02-14 11:17:05,687 DEBUG [org.hibernate.jdbc.ConnectionManager] - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
2007-02-14 11:17:05,687 DEBUG [org.hibernate.jdbc.JDBCContext] - after transaction completion
2007-02-14 11:17:05,687 DEBUG [org.hibernate.jdbc.ConnectionManager] - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
2007-02-14 11:17:05,687 DEBUG [org.hibernate.impl.SessionImpl] - after transaction completion
2007-02-14 11:17:05,687 WARN [org.springframework.remoting.support.RemoteInvocationTraceInterceptor] - Processing of HttpInvokerServiceExporter remote call resulted in fatal exception: dao.GenericDao.save
java.lang.NullPointerException
   at org.hibernate.engine.StatefulPersistenceContext.proxyFor(StatefulPersistenceContext.java:657)
   at org.hibernate.type.ComponentType.instantiate(ComponentType.java:492)
   at org.hibernate.type.ComponentType.replace(ComponentType.java:459)
   at org.hibernate.type.TypeFactory.replace(TypeFactory.java:495)
   at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:377)
   at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:179)
   at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
   at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687)
   at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669)
   at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245)
   at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
   at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
   at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
   at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
   at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
   at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:194)
   at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
   at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687)
   at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669)
   at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245)
   at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
   at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
   at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
   at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
   at org.hibernate.event.def.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:407)
   at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:266)
   at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120)
   at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
   at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
   at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
   at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
   at org.springframework.orm.hibernate3.HibernateTemplate$23.doInHibernate(HibernateTemplate.java:755)
   at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:362)
   at org.springframework.orm.hibernate3.HibernateTemplate.merge(HibernateTemplate.java:752)
   at dao.impl.hibernate.GenericHibernateDao.save(GenericHibernateDao.java:212)
   


Does anybody have any idea?

Thanx
Wenca[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 14, 2007 12:48 pm 
Newbie

Joined: Wed Feb 14, 2007 2:51 am
Posts: 5
Yes, that's true. I realized it after reading your post. Thanks.

So it would work only if merge is used with only one level of transient instancies, right? But if I have a transient instance that is a parent of another transient instance, the lower cannot be persisted because merge doesn't populate the ID into its parent.

Thanks again
Wenca

kochcp wrote:
saveOrUpdate does not have the same functionality as merge.

If you merge() a transient object and it has no identity set (b/c it is getting autogenerated by the database), the object that was merged will still not have an id after the merge() operation. But with saveOrUpdate(), it will.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 14, 2007 1:32 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
with merge, think so

wencax wrote:
So it would work only if merge is used with only one level of transient instancies, right? But if I have a transient instance that is a parent of another transient instance, the lower cannot be persisted because merge doesn't populate the ID into its parent.

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


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