I have a table named Employee which has a complex primary key i.e. a combination of 3 of its column
firstName : String
SecondName : String
bossId : foreingKey of other table named Boss ( auto generated database sequence)
And here is my code:
@Entity
@Table(name = "Employee")
@org.hibernate.annotations.Entity(optimisticLock = OptimisticLockType.ALL, dynamicUpdate = true)
public class Employee {
private EmployeePk employeePk;
private int age;
private String status;
@EmbeddedId
public EmployeePk getEmployeePk() {
return employeePk;
}
public void setEmployeePk(EmployeePk employeePk) {
this.employeePk = employeePk;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null ||
!(o instanceof Employee)) {
return false;
}
Employee other
= (Employee)o;
// if the id is missing, return false
if (getEmployeePk() == null) return false;
if( getEmployeePk().equals(other.getEmployeePk())) {
return true;
} else {
return false;
}
}
@Override
public int hashCode() {
if (getEmployeePk() != null) {
return getEmployeePk().hashCode();
} else {
return super.hashCode();
}
}
}
@Embeddable
public class EmployeePk implements Serializable{
private static final long serialVersionUID = -7827123517392541880L;
private String firstName;
private String secondName;
private Boss boss;
@ManyToOne
@JoinColumn(name = "boss_id",insertable= false, updatable= false)
public Boss getBoss() {
return boss;
}
public void setBoss(
Boss boss) {
this.boss = boss;
}
/* setters and getters of all with @column annotation */
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof EmployeePk)) {
return false;
}
EmployeePk other = (EmployeePk) obj;
if( getfirstname() != null &&
getFirstName().equals(other.getFirstName()) &&
getSecondName() !=null &&
getSecondName().equals(other.getSecondName()) &&
getBoss() != null &&
getBoss().getId() == other.getBoss().getId())
return true;
return false;
}
@Override
public int hashCode() {
if (getFirstName() != null &&
getSecondName() != null &&
getBoss() != null) {
return getFirstName().hashCode() +
getSecondName().hashCode();
} else {
return super.hashCode();
}
}
}
Now , everything is running fine and I am able to create/update/delete the database rows in Employee table.
But when i am trying to update same rows in one single transaction I am getting this exception :
org.hibernate.event.def.AbstractFlushingEventLis
tener: Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect):
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1792)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2435)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:64)
at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:996)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1141)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.impl.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:835)
I had similar issue with another table named Contractor but was able to solve this issue by overriding its equals and hashCode methods.
The thing is that in that table there was only one primary key named "id" which was a database auto generated sequence and hence there
was no concept of EmbeddedId
there.
I am not sure where I am going wrong here. I have spent several days in fixing this issue and followed several links for example: http://onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=1