Мне очень тяжело пытаться заставить однонаправленные отношения один-к-одному работать с JPA (Поставщик: Hibernate). По моему мнению, это не должно быть слишком хлопотно, но, по-видимому, JPA / Hibernate не согласны с этим; -)
Проблема в том, что мне нужно отобразить унаследованную схему, которую я не могу изменить, и что эта схема использует общий первичный ключ между двумя сущностями, который одновременно является внешним ключом для одной сущности.
Я создал простой TestCase:
БД выглядит следующим образом:
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;
Родитель (= владеющая сторона один-к-одному) выглядит следующим образом:
@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 не знает, как назначить идентификатор для ребенка. Однако я также попытался использовать Hibernates Generator «чужого» ключа, но также безуспешно, потому что нужно иметь обратную ссылку на родителя от child, что нежелательно.
Эта проблема не кажется мне слишком необычной, так чего мне здесь не хватает? Есть ли решение вообще? Я также могу использовать hibernate-расширения, если чистый JPA не дает решения.
Мои ожидания от правильного поведения были бы:
Если я попытаюсь настаивать на родителе с прикрепленным ребенком:
- получить идентификатор из последовательности, установить его на родительском
- настойчивый родитель
- установить идентификатор родителя для ребенка
- настойчивый ребенок
Если я попытаюсь сохранить «автономный» дочерний элемент (например, entityManager.persist (aChild)), я ожидаю исключение RuntimeException.
Любая помощь очень ценится!