1

複雑な主キー、つまり3つの列の組み合わせを持つEmployeeという名前のテーブルがあります

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 テーブルのデータベース行を作成/更新/削除できます。

しかし、1 つのトランザクションで同じ行を更新しようとすると、次の例外が発生します。

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」という名前の主キーが1つしかなかったため、そこにという概念がなかったEmbeddedIdことです。

ここでどこが間違っているのかわかりません。この問題の修正に数日を費やし、次のようないくつかのリンクをたどりました。ページ=1

4

1 に答える 1

0

いくつかの考え:

1) optimisticLock = OptimisticLockType.ALL を使用すると、疑わしくなります。私はこれを自分で使用したことはありませんが、あなたのエラーと関係があるのではないかと思います.

2) equals メソッドは、属性のいずれかが null の場合を処理するとは思わない。両方のインスタンスが同一であっても、常に false を返します。

3) Hibernate は、自然キーよりも専用の id (および必要に応じてバージョン) 列を使用する場合を本当に好みます。私の経験では、複合/自然キーのサポートは面倒でバグが多いようです。

于 2012-08-27T21:48:09.840 に答える