-->
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.  [ 2 posts ] 
Author Message
 Post subject: Composite key is not saved, stale key value is used
PostPosted: Wed Dec 03, 2008 2:34 pm 
Newbie

Joined: Wed Dec 03, 2008 1:57 pm
Posts: 2
Hi, new user here. I am trying to save an object with a composite key. The first object is saved fine, but all consecutive objects cannot be saved because of PK violation. The reason is that Hibernate uses stale ID value despite that I set it explicitly.

What I don't get is that my composite key consists of object ID and object version (later this object/table is supposed to be linked to the parent object with object ID only, thus creating one-to-many relationship). Anyway, I set both the ID (which is UUID) and version (int) explicitly. Hibernate uses version that I set, but reuses stale ID value. Why such a preference to the ID?

Here is the DB schema:

Code:
CREATE TABLE [dbo].[myobj](
   [myobj_id] [uniqueidentifier] NOT NULL,
   [myobj_version] [int] NOT NULL,
   [name] [nvarchar](100) NULL
        CONSTRAINT [PK_MYOBJ] PRIMARY KEY
        ( [myobj_id] ASC, [myobj_version] ASC )
)


The PK:

Code:
@Embeddable
public class MyObjPK implements Serializable {
   static final long serialVersionUID = -8323397299604599234L;

   @Column(name = "myobj_id", nullable = false, updatable = false, insertable = true)
   private UUID myobjId;
   public UUID getMyObjId() {return myobjId;}
   public void setMyObjId(UUID id) {this.myobjId = id;}
       
   @Column(name = "myobj_version", nullable = false, updatable = false, insertable = true)
   private int version;
   public int getVersion() {return version;}
   public void setVersion(int myobjVersion) {this.version = myobjVersion;}
   
   public MyObjPK() {}
   
   public MyObjPK(UUID id, int version) {
      this.myobjId = id;
      this.version = version;
   }

   public int hashCode() {
      return 31 * myobjId.hashCode() + version;
   }
      
   public boolean equals (Object other) {
      if (other == null) return false;
      if (!(other instanceof MyObjPK)) return false;
      MyObjPK that = (MyObjPK) other;
      return this.myobjId.equals(that.myobjId) && this.version == that.version;
   }
}


The entity:

Code:
@Entity
@Table(name = "myobj")
public class MyObjEntity implements IMyObj {

   static final long serialVersionUID = -8233297299688457234L;

   @EmbeddedId
   private MyObjEntityPK myObjEntityPK;
   public MyObjEntityPK getMyObjEntityPK() { return myObjEntityPK; }
   public void setMyObjEntityPK(MyObjEntityPK myObjEntityPK) { this.myObjEntityPK = myObjEntityPK; }

   private String name;
   @Column(name = "name")
   public String getMyObjName() {return name;}
   public void setMyObjName(String name) {this.name = name;}

   public MyObjEntity() {}

   public MyObjEntity(MyObj myObj) {
      myObjEntityPK = new MyObjEntityPK(myObj.getId(), myObj.getVersion());
      setMyObjName(myObj.getMyObjName());
   }

   public int getVersion() { return myObjEntityPK.getVersion(); }
   public void setVersion(int version) { myObjEntityPK.setVersion(version); }

   public UUID getId() { return myObjEntityPK.getMyObjId(); }
   public void setId(UUID id) { myObjEntityPK.setMyObjId(id); }


   public int hashCode() {
      return myObjEntityPK.hashCode();
   }
   
   public boolean equals (Object other) {
      if (other == null) return false;
      if (!(other instanceof MyObjEntity)) return false;
      MyObjEntity that = (MyObjEntity) other;
      return myObjEntityPK.getMyObjId().equals(that.getId()) && myObjEntityPK.getVersion() == that.getVersion();
   }
   
}


Id and Version getters/setters are in the entity because the IMyObj requires them, I have to implement it.

Then I simply save the object like this:

Code:
MyObj myObj = new MyObjDefaultImpl();
myObj.setMyObjName("Test data");
myObj.setId(UUID.randomUUID());
myObj.setVersion(1);
...
someplace later:
...
MyObjEntity myObjEntity = myObj instanceof MyObjEntity ? (MyObjEntity)myObj : new MyObjEntity(myObj);
em.persist(myObjEntity);


I can set any version I want and it is persisted, but for the Id an old stale value is used, if anyone is interested it is "0500EDAC-7273-0E00-6A61-76612E757469".

I turned Hibernate caching off. I checked my equals() and hashcode() methods. I checked value of serialVersionUID. Can anyone give me a clue what is happening?

Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2008 3:19 pm 
Newbie

Joined: Wed Dec 03, 2008 1:57 pm
Posts: 2
No one can help? Seems that no one has encountered this issue. I can add another bit of information.

If both properties of my composite key are int values, then composite key works as it is supposed to. But after I changed one of the properties to a UUID, it stopped working again and select statement displayed the same value for the UUID-typed property: 0500EDAC-7273-0E00-6A61-76612E757469 The same value is used for inserts despite that I explicitly set it in the object, so I can insert only one row in the table.

Database is MS SQL 2005. hibernate-3.2.5.ga, hibernate-annotations-3.3.0.ga, hibernate-commons-annotations-3.0.0.ga, hibernate-entitymanager-3.3.1.ga, hibernate-support-0.13.0, hibernate-validator-3.0.0.ga.

Either the DB or Hibernate reuses the same value for the UUID propertly. This smells like a bug to me, if no one knows an answer I will file this as a bug.


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