-->
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: NonUniqueObjectException only in debug mode
PostPosted: Tue Apr 22, 2008 1:34 pm 
Newbie

Joined: Tue Apr 22, 2008 12:47 pm
Posts: 3
Location: Russia, Moscow
After a call saveOfUpdate(project) sometimes NonUniqueObjectException is thrown. project object have id==0 and is not attached to session.

I've read plenty of topics in the internet, that claims about get()/load() in the incorrect places.
But strangest thing for my problem is that it depends on debugging mode.

When I step into next method and then step over its lines then error does not appear.
Code:
   private void addNewProjectToPerson(Person dbPerson) {
      project.setPerson(dbPerson);
      hibernateSessionFactory.getCurrentSession().saveOrUpdate(project); // here is the place where exception will be thrown
      dbPerson.getProjects().add(project);
   }

But is I step over this method, then error appears.

I do not understand how debugging mode could be connected with Hibernate exceptions. I believe, that I did not make the same mistake as everybody who usually gets NonUniqueObjectException.

Error scenario is reproducible on the same http calls from browser on the same database data.

Where should I look for the cause of the problem?
Should I try to create something smaller, that shows the same error?
Should I debug Hibernate throws its sources?
Should I try other version of Hibernate?

What else could you suggest me?

I've spend more than two days isolating this error scenario and trying different things to solve it. Looks like I still have this error.

I will be grateful for any help or yours suggestions.

Hibernate version:
3.2.6 + 3.3.1 Hibernate Annotations

Full stack trace of any exception that occurs:
ERROR 22.04.2008 17:13:05,124 [http-8080-Processor23] [[default]] Servlet.service() for servlet default threw exception
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [my.company.entities.Project#26]
at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:590)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:303)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
at $Proxy20.saveOrUpdate(Unknown Source)

Name and version of the database you are using:
MySQL 5


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 22, 2008 5:12 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
is it possible you have some unusual code in toString()?
Some debuggers implicitly call it to show you the current state in GUI,
but could affect you entity; eg. you could concatenate some uninitialized field, which gets initialized because of the debug mode.

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 24, 2008 10:05 am 
Newbie

Joined: Tue Apr 22, 2008 12:47 pm
Posts: 3
Location: Russia, Moscow
Thank you for your answer s.grinovero.
I deleted all toString() methods from all entity classes, nothing changed.

I have verified, that Hibernate version is not the cause of the problem.

Just as a reference Project class and Person class.

Code:
package my.company.entities;

import com.opensymphony.xwork2.conversion.annotations.Conversion;
import com.opensymphony.xwork2.conversion.annotations.TypeConversion;

import javax.persistence.*;
import java.util.Date;

@Entity
@Conversion
public class Project implements SearchablePart {

   @Id @GeneratedValue private long id;

   private String name;
   @Temporal(value = TemporalType.DATE)
   private Date startDate;
   @Temporal(value = TemporalType.DATE)
   private Date endDate;
   private String site;
   @Lob private String comments;
   @ManyToOne private Person person;
   private String role;

   @Transient
   public Searchable getSearchableOwner() {
      return person;
   }

   public Date getStartDate() { return startDate; }

   @TypeConversion(converter = "my.company.web.util.StringToDateTypeConverter")
   public void setStartDate(Date startDate) { this.startDate = startDate; }

   public Date getEndDate() { return endDate; }

   @TypeConversion(converter = "my.company.web.util.StringToDateTypeConverter")
   public void setEndDate(Date endDate) { this.endDate = endDate; }

   // all getter/setter without @ were omitted
}


Code:
package my.company.entities;

import com.opensymphony.xwork2.conversion.annotations.Conversion;
import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
import my.company.search.SearchDataType;

import javax.persistence.*;
import java.io.Serializable;
import java.util.*;

@Entity
@Conversion
public class Person extends Loginable implements Serializable, Searchable {

   /** Says how many invites can the new Zubberki user give out by default */
   public static final int DEFAULT_INVITES_PER_PERSON = 20;

   @Id @GeneratedValue private long id;

   @Column(columnDefinition = "VARBINARY(255)")
   private byte[] passwordHash;

   @Temporal(value = TemporalType.DATE)

   // many irrelevant fields were omitted

   private int invitesLeft = DEFAULT_INVITES_PER_PERSON;

   private boolean priviledged = false;

   @OneToOne private ImageLink userPic;
   @ManyToMany private Set<Category> categories;
   @OneToMany(mappedBy = "person")
   private Set<Project> projects = new HashSet<Project>();
   @OneToMany(mappedBy = "person")
   private Set<Education> educations = new HashSet<Education>();
   @ManyToMany(cascade = { CascadeType.ALL })
   private Set<Communicator> favoriteCommunicators = new HashSet<Communicator>();
   @OneToMany(mappedBy = "person")
   private Set<Organization> organizations = new HashSet<Organization>();
   @OneToMany(mappedBy = "owner")
   private List<Document> documents = new ArrayList<Document>();

   @Transient
   public SearchDataType getSearchDataType() {
      return SearchDataType.PERSON;
   }

   @Transient
   public Project getProject(long projectId) {
      if(projects == null) return null;
      for(Project project : projects) {
         if(project.getId() == projectId) {
            return project;
         }
      }
      return null;
   }

   @Transient
   public Organization getOrganization(long orgRoleId) {
      if(organizations == null) return null;
      for(Organization organization : organizations) {
         if(organization.getId() == orgRoleId) {
            return organization;
         }
      }
      return null;
   }

   @Transient
   public Education getEducation(long educationId) {
      if(educations == null) return null;
      for(Education education : educations) {
         if(education.getId() == educationId) {
            return education;
         }
      }
      return null;
   }

   // many getters/setters without @ were omitted   

   public Date getBirthDate() { return birthDate; }

   @TypeConversion(converter = "my.company.web.util.StringToDateTypeConverter")
   public void setBirthDate(Date birthDate) { this.birthDate = birthDate; }

}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 24, 2008 6:21 pm 
Newbie

Joined: Tue Apr 22, 2008 12:47 pm
Posts: 3
Location: Russia, Moscow
Finally I found a root cause of a problem.

Code:
public class Project implements SearchablePart {
   @Transient
   public Searchable getSearchableOwner() {
      return person;
   }


Code:
session.sync(project) {
   call onPostInsert(PostInsertEvent event)
      1) Gets person through project.getSearchableOwner()
      2) Iterate through all projects of a person, which instantiates all projects
   call checkUniqueness(EntityKey key, Object object)
      1) Check for uniqueness of a project deeply inside .sync
      2) But project were already created, so .sync() thinks, that this is another one project (I suppose) and throws exception.
}


I do not understand why debugging mode changes this behavior, cause I did not set any breakpoints inside .sync(project) call, only outside.

I will try to find some workaround to make this work.


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.