Kri*_*den 29 java annotations hibernate composite-key one-to-many
我正在使用带注释的Hibernate(在spring中),并且我有一个对象,它有一个有序的,多对一的关系,一个子对象有一个复合主键,其中一个组件是一个外键回到父对象的id.
结构看起来像这样:
+=============+ +================+
| ParentObj | | ObjectChild |
+-------------+ 1 0..* +----------------+
| id (pk) |-----------------| parentId |
| ... | | name |
+=============+ | pos |
| ... |
+================+
Run Code Online (Sandbox Code Playgroud)
我尝试了各种注释组合,但似乎都没有.这是我能够提出的最接近的:
@Entity
public class ParentObject {
@Column(nullable=false, updatable=false)
@Id @GeneratedValue(generator="...")
private String id;
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER, cascade={CascadeType.ALL})
@IndexColumn(name = "pos", base=0)
private List<ObjectChild> attrs;
...
}
@Entity
public class ChildObject {
@Embeddable
public static class Pk implements Serializable {
@Column(nullable=false, updatable=false)
private String parentId;
@Column(nullable=false, updatable=false)
private String name;
@Column(nullable=false, updatable=false)
private int pos;
@Override
public String toString() {
return new Formatter().format("%s.%s[%d]", parentId, name, pos).toString();
}
...
}
@EmbeddedId
private Pk pk;
@ManyToOne
@JoinColumn(name="parentId")
private ParentObject parent;
...
}
Run Code Online (Sandbox Code Playgroud)
经过长时间的一次实验,我到达了这里,其中我的大部分尝试都产生了实体,这些实体甚至因各种原因无法加载.
更新:感谢大家的评论; 我取得了一些进展.我做了一些调整,我认为它更接近(我已经更新了上面的代码).但是,现在问题在于插入.父对象似乎保存得很好,但是子对象没有保存,而我能够确定的是hibernate没有填写子对象的(复合)主键的parentId部分,所以我'得到一个不唯一的错误:
org.hibernate.NonUniqueObjectException:
a different object with the same identifier value was already associated
with the session: [org.kpruden.ObjectChild#null.attr1[0]]
Run Code Online (Sandbox Code Playgroud)
我在我自己的代码中填充name和pos属性,但当然我不知道父ID,因为它尚未保存.关于如何说服hibernate填写这个的任何想法?
谢谢!
RTB*_*ard 16
Manning一书Java Persistence with Hibernate在第7.2节中有一个例子,概述了如何做到这一点.幸运的是,即使你没有自己的书,你可以通过下载的JPA版本中看到的这个源代码示例买者自负样本项目(直接链接在此),并检查类Category和CategorizedItem在auction.model包中.
我还将总结下面的关键注释.如果它仍然不合适,请告诉我.
ParentObject:
@Entity
public class ParentObject {
@Id @GeneratedValue
@Column(name = "parentId", nullable=false, updatable=false)
private Long id;
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@IndexColumn(name = "pos", base=0)
private List<ChildObject> attrs;
public Long getId () { return id; }
public List<ChildObject> getAttrs () { return attrs; }
}
Run Code Online (Sandbox Code Playgroud)
ChildObject:
@Entity
public class ChildObject {
@Embeddable
public static class Pk implements Serializable {
@Column(name = "parentId", nullable=false, updatable=false)
private Long objectId;
@Column(nullable=false, updatable=false)
private String name;
@Column(nullable=false, updatable=false)
private int pos;
...
}
@EmbeddedId
private Pk id;
@ManyToOne
@JoinColumn(name="parentId", insertable = false, updatable = false)
@org.hibernate.annotations.ForeignKey(name = "FK_CHILD_OBJECT_PARENTID")
private ParentObject parent;
public Pk getId () { return id; }
public ParentObject getParent () { return parent; }
}
Run Code Online (Sandbox Code Playgroud)
您应该将ParentObject引用仅合并,ChildObject.Pk而不是分别映射parent和parentId:
(与问题无关的getter,setter,Hibernate属性和成员访问关键字被省略)
class ChildObject {
@Embeddable
static class Pk {
@ManyToOne...
@JoinColumn(name="parentId")
ParentObject parent;
@Column...
String name...
...
}
@EmbeddedId
Pk id;
}
Run Code Online (Sandbox Code Playgroud)
在ParentObject你那么只要把@OneToMany(mappedBy="id.parent")和它的作品。
经过多次尝试和挫折后,我最终确定我不能完全做我想做的事。
最终,我继续为子对象提供了自己的合成密钥,并让 Hibernate 管理它。这并不理想,因为密钥几乎与其余数据一样大,但它有效。
| 归档时间: |
|
| 查看次数: |
64454 次 |
| 最近记录: |