3つのクラス間の共有PKと一対一エンティティの関連付けを休止
-
18-09-2019 - |
質問
私は3つのJavaクラスのオブジェクト間の単方向の1対1の関係たいです。私は、オブジェクトが同じことを共有したいPKすなわち、すべての人は、対応する心臓や肝臓、person.person_id = heart.heart_id = liver.liver_idを持っています。各フィールドの負荷を持っているので、私は1に3つのテーブルをマージする必要はありません。ここに私のコードは、(主にこの質問のに基づいて)です。
@Entity
public class Person {
public long personId;
private String name;
public Heart heart;
public Liver liver;
// other fields
@Id
@GeneratedValue
public long getPersonId() {return personId;}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Heart getHeart() {return heart;}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Liver getLiver() {return liver;}
// other getters and setters and constructors
}
@Entity
public class Heart {
private long heartId;
private int bpm;
private Person person;
// other fields
@Id
@GenericGenerator(
name = "generator",
strategy = "foreign",
parameters = @Parameter(name = "property", value = "person")
)
@GeneratedValue(generator = "generator")
public long getHeartId() {return heardId;}
@OneToOne(mappedBy="heart")
@PrimaryKeyJoinColumn
public Person getPerson() {return person;}
// other getters and setters and constructors
}
@Entity
public class Liver {
private long liverId;
private boolean healthy;
private Person person;
// other fields
// the rest uses the same hibernate annotation as Heart
}
私のセットアップセッションをし、次の操作を行います:
Person jack = new Person();
jack.setName("jack");
Heart heart = new Heart();
heart.setBpm(80);
Liver liver = new Liver();
liver.setHealthy(true);
は、その後、私はそれの臓器を持つ人物オブジェクトをリンクアップし、それを保存した場合、私はエラーを取得する(注:私はちょうど2クラス、例えば人と心を使用したとき、私は同じ動作を得た):
jack.setHeart(heart);
jack.setLiver(liver);
session.save(jack);
org.hibernate.id.IdentifierGenerationException:ヌル一対一のプロパティからIDを割り当てようとしました:人
しかし、それは私が関係を設定した場合、両方の方法を動作します:
jack.setHeart(heart);
heart.setPerson(jack);
jack.setLiver(liver);
liver.setPerson(jack);
session.save(jack);
しかし、確かにこれは一方向の関係のために必要ではないでしょうか?
乾杯
PS。奇妙なことに、私はそれが動作します私は、例えば2クラスを使用する場合(DBに両方のオブジェクトが保存されます)注意してください人と心、そして私はちょうどリンクに他の方法を設定します:
heart.setPerson(jack);
session.save(heart);
とにかく、しかし、私は(そうそれはあなたがセットアップする必要がありますすべてです、それはそれは自身のPKだし、他の人がそれを使用して自動-生成とその人は、親オブジェクトである私には論理的なようだ)、この作業の理由はわかりません私は私の3クラスの状況に、この加工方法を適用する方法を見つけ出すことはできません...
解決
私はこれを言うことを憎むが、あなたはそこに双方向の関係を有しています。人の心と肝臓への参照を持っており、それらのそれぞれは、背面人への参照を持っています。あなたはあなたの心と肝臓のIDプロパティに設定した注釈は、特に彼らは人のプロパティに委譲することで自分のIDプロパティの値を取得すると言っています。あなたが動作しないことが示さきた例では、あなたはまだそれらの人の人物プロパティを設定していないので、彼らは明らかに自分のID値を取得することはできません。
あなたはHibernateの注釈のマニュアルに記載された、真の単方向OneToOne、この関係を設定することができますいずれかます:
@Entity
public class Body {
@Id
public Long getId() { return id; }
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Heart getHeart() {
return heart;
}
...
}
@Entity
public class Heart {
@Id
public Long getId() { ...}
}
またはあなたが私たちの実体は、次のような関係の両側をフック合理化するために、わずかにオブジェクトを変更することができます
@Entity
public class Person {
public long personId;
private String name;
public Heart heart;
public Liver liver;
// other fields
@Id
@GeneratedValue
public long getPersonId() {return personId;}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Heart getHeart() {return heart;}
public void setHeart(Heart heart){
this.heart = heart;
this.heart.setPerson(this);
}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Liver getLiver() {return liver;}
public void setLiver(Liver liver){
this.liver = liver;
this.liver.setPerson(this);
}
// other getters and setters and constructors
}
他のヒント
私はそれを試していないが、私はそれを言うでしょう....
両側の差がPerson
クラスは彼のマッピングにのmappedBy
何のを持たないことです。
ですから、それぞれ1対1のために、Person
は基準値、Hibernateは公式として考えるものを持っています。逆に、他のオブジェクトの上に、mappedBy
は、そのオブジェクトにマッピングされたプロパティを値を使用しますが、そのオブジェクトに移動し、考慮していないために休止することを示します。
私が正しいならば、あなたは何mappedBy
を持っていない唯一の値を設定し、Person
オブジェクトを保存する(それがカスケードを有するものであるため)、そして結果が正しいかどうかを確認できたの..チェックするには)