JPA(プロバイダー:Hibernate)と連携するために一方向の1対1の関係を取得しようとすると非常に苦労しています。私の意見では、これはそれほど面倒なことではないはずですが、明らかにJPA/Hibernateはそれに同意しません;-)
問題は、変更できないレガシースキーマをマップする必要があることと、このスキーマが2つのエンティティ間で共有される主キーを使用することです。これは同時に1つのエンティティの外部キーです。
簡単なTestCaseを作成しました。
DBは次のようになります。
CREATE TABLE PARENT (PARENT_ID Number primary key, Message varchar2(50));
CREATE TABLE CHILD (CHILD_ID Number primary key, Message varchar2(50),
CONSTRAINT FK_PARENT_ID FOREIGN KEY (CHILD_ID )REFERENCES PARENT (PARENT_ID));
CREATE SEQUENCE SEQ_PK_PARENT START WITH 1 INCREMENT BY 1 ORDER;
親(= 1対1の所有側)は次のようになります。
@Entity
@Table(name = "PARENT")
public class Parent implements java.io.Serializable {
private Long parentId;
private String message;
private Child child;
@Id
@Column(name = "PARENT_ID", unique = true, nullable = false, precision = 22, scale = 0)
@SequenceGenerator(name="pk_sequence", sequenceName="SEQ_PK_PARENT")
@GeneratedValue(generator="pk_sequence", strategy=GenerationType.SEQUENCE)
public Long getParentId() {
return this.parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
@Column(name = "MESSAGE", length = 50)
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
@OneToOne (cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn(name="PARENT_ID", referencedColumnName="CHILD_ID")
public Child getTestOneToOneChild() {
return this.child;
}
public void setTestOneToOneChild(Child child) {
this.child = child;
}
}
子供:
@Entity
@Table(name = "TEST_ONE_TO_ONE_CHILD", schema = "EXTUSER")
public class Child implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Long childId;
private String message;
public Child() {
}
public Child(String message) {
this.message = message;
}
@Id
@Column(name = "CHILD_ID")
public Long getChildId() {
return this.childId;
}
public void setChildId(Long childId) {
this.childId = childId;
}
@Column(name = "MESSAGE", length = 50)
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
}
JPAが子のIDを割り当てる方法を知らないという問題を完全に理解しています。ただし、Hibernatesの「外部」キージェネレーターを使用しようとしましたが、これも成功しませんでした。これは、子から親への逆参照が必要であり、望ましくないためです。この問題は私にはそれほど珍しいことではないようですが、ここで何が欠けていますか?解決策はありますか?純粋なJPAで解決策が提供されない場合は、Hibernate拡張機能を使用することもできます。
正しい振る舞いに対する私の期待は次のとおりです。子供を付けたまま親を維持しようとすると、次のようになります。
- シーケンスからIDを取得し、親に設定します
- 親を永続化する
- 子に親のIDを設定する
- 子を持続させる
「スタンドアロン」の子(entityManager.persist(aChild)など)を永続化しようとすると、RuntimeExceptionが発生します。
どんな助けでも大歓迎です!