【发布时间】:2011-06-12 23:57:27
【问题描述】:
我很难尝试建立单向的一对一关系来使用 JPA(提供者:Hibernate)。在我看来,这应该不会太麻烦,但显然 JPA / Hibernate 不同意这一点;-)
问题是我必须映射一个我无法更改的旧架构,并且此架构在两个实体之间使用共享主键,同时又是一个实体的外键。
我创建了一个简单的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;
父母(=一对一的拥有方)如下所示:
@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 不提供解决方案,我也可以使用休眠扩展。
我对正确行为的期望是: 如果我尝试坚持带孩子的父母:
- 从序列中获取 ID,设置在父节点上
- 坚持父母
- 为孩子设置父母的 ID
- 坚持孩子
如果我尝试持久化一个“独立”子级(例如 entityManager.persist(aChild)),我预计会出现 RuntimeException。
非常感谢任何帮助!
【问题讨论】:
-
我还没有尝试过,但它可能会起作用,因为您在 getter 上添加了注释,这应该告诉 Hibernate 使用 setter 填充您的 POJO。您可以尝试在 setParentId() 和 setChild() 方法中设置子 ID(如果还没有)。
-
不,这不起作用:IdentifierGenerationException:必须在调用 save() 之前手动分配此类的 ID
-
你使用哪个版本的 Hibernate?
-
@axtavt:我查看了 maven poms。显然那里有多个休眠版本,分别是 3.2.6ga 和 3.3.0.SP1。我需要一段时间才能弄清楚使用的版本,因为这个项目中的 maven 设置有点麻烦。我会及时通知你
-
您必须删除父级中@OneToOne 中的级联属性。请参阅我对单向一对一关系的回答(您必须手动处理级联操作)。单独添加孩子也会导致异常,因为没有为其分配 id。stackoverflow.com/questions/7892571/…
标签: java hibernate jpa jakarta-ee one-to-one