我有一个名为 Employee 的表,它有一个复杂的主键,即它的 3 个列的组合
firstName : String
SecondName : String
bossId : foreingKey of other table named Boss ( auto generated database sequence)
这是我的代码:
@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();
}
}
}
现在,一切运行良好,我可以在 Employee 表中创建/更新/删除数据库行。
但是当我试图在一个事务中更新相同的行时,我得到了这个异常:
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)
我在另一个名为 Contractor 的表中遇到了类似的问题,但能够通过覆盖其 equals 和 hashCode 方法来解决这个问题。
问题是在那个表中只有一个名为“id”的主键,它是一个数据库自动生成的序列,因此没有那里的概念EmbeddedId
。
我不确定我在哪里出错了。我花了几天时间来解决这个问题,并关注了几个链接,例如: http: //onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?页=1