I'm having a very hard time trying to get a unidirectional one-to-one relationship to work with JPA (Provider: Hibernate). In my opinion this should not be too much of a hassle but apparently JPA / Hibernate disagrees on that ;-)
The problem is that I have to map a legacy schema which I cannot change and that this schema uses a shared primary key between two entities which at the same time is the foreign key for one entity.
I created a simple TestCase:
DB looks as follows:
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;
The parent(=owning side of one-to-one) looks as follows:
@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;
}
}
The 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;
}
}
I totally see the problem that JPA does not know how to assign the id for the child. However I also tried using Hibernates "foreign" key Generator with also no success because that one needs to have a back reference to the parent from child which is not desirable.
This problem does not seem too uncommon to me, so what am I missing here? Is there a solution at all? I can also use hibernate extensions if pure JPA does not provide a solution.
My expectations for a correct behavior would be:
If I try to persist the parent with a child attached:
- get ID from sequence, set it on the parent
- persist parent
- set parent's ID on child
- persist child
If I try to persist a "standalone" child (e.g. entityManager.persist(aChild)) I would expect a RuntimeException.
Any help is greatly appreciated!
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…