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!