JPA 中与超类实体属性的双向关系
我想用 JPA 实现一些树状结构。 我有一个“文件夹”实体和一个“测试”实体。文件夹可以包含文件夹和测试。测试不包含任何内容。
测试和文件夹都有一个 Node 超类,看起来像这样:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Node implements TreeNode, Serializable{
private Long id;
String description;
String name;
@ManyToOne
Node parent;
...getters, setters and other stuff that doesnt matter...
}
这是文件夹类:
@Entity
public class Folder extends Node{
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade=CascadeType.ALL, **mappedBy="parent"**)
List<Folder> folders;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade=CascadeType.ALL, **mappedBy="parent"**)
List<Test> tests;
...
}
所以主要问题是mappedBy属性,它与祖先中未覆盖的超类属性相关,因为我得到了这样的异常:
Exception while preparing the app : mappedBy reference an unknown target entity property: my.test.model.Folder.parent in my.test.model.Folder.folders
可能有一些文件夹类的“文件夹”和“测试”属性的棘手映射,我需要一些帮助。
编辑:我使用 targetEntity=Node.class 指定了文件夹类的文件夹和测试属性:
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade=CascadeType.ALL, mappedBy="parent",targetEntity=Node.class)
List<Folder> folders;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade=CascadeType.ALL, mappedBy="parent",targetEntity=Node.class)
List<Test> tests;
并且它可以工作。但效果不太好。现在,当我需要单独获取它们时,测试和文件夹都映射到 both 属性(我不知道为什么我没有收到异常)。
所以我仍在寻找合适的映射来实现这一目标。我会感谢任何帮助。
I'm tying to implement some tree-like structure with JPA.
I have a "folder" entity and a "test" entity. Folder can contain both folders and tests. Test doesnt contains anything.
Both test and folder have a Node superclass, looks like this:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Node implements TreeNode, Serializable{
private Long id;
String description;
String name;
@ManyToOne
Node parent;
...getters, setters and other stuff that doesnt matter...
}
And here is the Folder class:
@Entity
public class Folder extends Node{
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade=CascadeType.ALL, **mappedBy="parent"**)
List<Folder> folders;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade=CascadeType.ALL, **mappedBy="parent"**)
List<Test> tests;
...
}
So the main problem is the mappedBy property, which relates to superclass property not overriden in ancestor, cause I got such exception:
Exception while preparing the app : mappedBy reference an unknown target entity property: my.test.model.Folder.parent in my.test.model.Folder.folders
There is might be some tricky mapping over "folders" and "test" properties of Folder class, and I need a little help with that.
EDIT: I specified both folders and tests properties of Folder class with targetEntity=Node.class:
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade=CascadeType.ALL, mappedBy="parent",targetEntity=Node.class)
List<Folder> folders;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade=CascadeType.ALL, mappedBy="parent",targetEntity=Node.class)
List<Test> tests;
And its gets work. But works not fine. Now both tests and folders mapped to both properties (I dont know why I'm not geting exceptions), when I need to get them separately.
So I'm still looking for a suitable mappings to achieve that. I would appriciate any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有趣的结构,可能包含很多挑战。但是关于与超类实体属性的关系的问题:不幸的是你不能用 Hibernate 做到这一点。您设置 targetEntityClass 的方法也不起作用,因为它从实体映射的角度有效地更改了集合元素的类型。
幸运的是有解决方法。您可以建立从实体到您扩展的 MappedSuperClass 属性的关系。可能您不想让 Node 成为 MappedSuperClass,因此您必须添加新的。然后它必须位于节点和文件夹之间:文件夹->MappedSuperClass->节点。它是这样的(这种方法至少适用于 Hibernate 3.5.6,不知道从哪个版本开始支持它):
顺便说一句,Node 对于 Parent 来说是不是有点太通用了?至少如果它仅用于此目的的话。所有的父母都是文件夹。
Interesting structure, probably contains many challenges. But to the question about relationship to superclass entitys property: unfortunately you cannot do that with Hibernate. Your approach to set targetEntityClass also does not work, because it effectively changes type of collection elements from entity mapping point of view.
Luckily there is workaround. You can have relationship from entity to the property of MappedSuperClass, which you extend. Likely you do not want to make Node to be MappedSuperClass, so you have to add new. And then it have to be located between Node and Folder: Folder->MappedSuperClass->Node. It goes like this (such a approach works at least with Hibernate 3.5.6, no idea since which version it is supported):
By the way, isn't Node bit too generic for Parent? At least if it is used only for this purpose. All parents are folders.