1

我有一个名为 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

4

1 回答 1

0

几个想法:

1) 使用optimisticLock = OptimisticLockType.ALL 让我怀疑。我自己从来没有使用过这个,但我怀疑它可能与你的错误有关。

2) 我认为 equals 方法不能处理任何属性为空的情况。即使两个实例相同,它也将始终返回 false。

3) Hibernate 真的更喜欢使用专用的 id(和版本,如果需要)列而不是自然键。根据我的经验,对复合/自然键的支持似乎很麻烦且有问题。

于 2012-08-27T21:48:09.840 回答