複雑な主キー、つまり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