JPA / JPQL:查找单向树的根元素
JPA / JPQL:查找单向树的根元素。
我需要一些帮助来为以下问题编写命名查询。
我有以下(简化的)实体(TNode)定义,并且可以通过 JPA 保存/读取它。 该实体是单向的,因此孩子不知道父母!
现在我尝试编写一个命名查询来获取所有根元素。
我使用 JPA 2.0 (Hibernate) 并在互联网上发现了一些提示,支持单向链接。
还附加了一个简单的 JUnit (4),用于创建两棵树并将其保存到数据库中。我删除了所有断言。
如果我运行 Junit,该表将按预期显示:
ID NAME CHILDS_ID
1 A1 (null)
2 A11 1
3 B1 (null)
4 B11 3
我添加了 @JoinColumn 以在同一个表中包含自引用。以及简单的 SQL 问题 很容易(WHERE childs_id = null)。但是我必须如何在 JPQL 中编写这个呢?
感谢您的回答。
Uwe
@Entity
@Table(name = "TNode")
@NamedQueries({ @NamedQuery(name = "getRootNodes", query = "FROM TNode tnode ......."), })
public class TNode implements JPAObject {
@Id
@GeneratedValue
private Integer id;
private String name;
@OneToMany(cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.REMOVE })
@JoinColumn
private Set<TNode> childs = new HashSet<TNode>();
// JPA only
private TNode() {
}
public TNode(String name) {
this.name = name;
}
public void add(TNode tNode) {
childs.add(tNode);
}
@Override
public Integer getId() {
return id;
}
@Override
public String getName() {
return name;
}
}
这里是简化的 Junit
@RunWith(Arquillian.class)
public class TNodeTest {
@Deployment
public static Archive<?> createTestArchive() {
//@formatter:off
Archive<?> archive = ShrinkWrap.create(WebArchive.class, "test.war")
.addPackages(true, DummyInterfaceForTest.class.getPackage())
.addAsLibraries(FindMavenArtifact.find("com.thoughtworks.xstream:xstream:1.4.2"))
.addAsLibraries(FindMavenArtifact.find("xmlpull:xmlpull:1.1.3.1"))
.addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml")
.addAsResource("import.sql", "import.sql")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
//@formatter:on
System.out.println(archive.toString(true));
return archive;
}
@Inject
@DAO.DAOType(type = DAO.MODE.STATELESS)
private DAO<JPAObject> dao;
@Test
public void testMutipleRoots() throws Exception {
TNode root;
root = new TNode("A1");
root.add(new TNode("A11"));
dao.saveOrUpdate(root);
root = new TNode("B1");
root.add(new TNode("B11"));
dao.saveOrUpdate(root);
}
}
JPA / JPQL: find root elements of a unidirectional tree.
I need some help to write a named query for the following problem.
I have the following (simplified) definition of an entity (TNode) and can save/read it via JPA.
The entity is unidirectional, so childs don't know the parent!
Now I try to write a named query to get all root elements.
I use JPA 2.0 (Hibernate) and found some hints in the internet, that unidirectional links are supported.
A simple JUnit (4) is also attached, to create two trees and save it into the db. I removed all the asserts.
If I run the Junit, the table looks as expected:
ID NAME CHILDS_ID
1 A1 (null)
2 A11 1
3 B1 (null)
4 B11 3
I added @JoinColumn to have the self reference in the same table. And the with simple SQL the problem
would be easy (WHERE childs_id = null). But how must I write this in JPQL?
Thanks for the answers.
Uwe
@Entity
@Table(name = "TNode")
@NamedQueries({ @NamedQuery(name = "getRootNodes", query = "FROM TNode tnode ......."), })
public class TNode implements JPAObject {
@Id
@GeneratedValue
private Integer id;
private String name;
@OneToMany(cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.REMOVE })
@JoinColumn
private Set<TNode> childs = new HashSet<TNode>();
// JPA only
private TNode() {
}
public TNode(String name) {
this.name = name;
}
public void add(TNode tNode) {
childs.add(tNode);
}
@Override
public Integer getId() {
return id;
}
@Override
public String getName() {
return name;
}
}
Here the simplified Junit
@RunWith(Arquillian.class)
public class TNodeTest {
@Deployment
public static Archive<?> createTestArchive() {
//@formatter:off
Archive<?> archive = ShrinkWrap.create(WebArchive.class, "test.war")
.addPackages(true, DummyInterfaceForTest.class.getPackage())
.addAsLibraries(FindMavenArtifact.find("com.thoughtworks.xstream:xstream:1.4.2"))
.addAsLibraries(FindMavenArtifact.find("xmlpull:xmlpull:1.1.3.1"))
.addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml")
.addAsResource("import.sql", "import.sql")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
//@formatter:on
System.out.println(archive.toString(true));
return archive;
}
@Inject
@DAO.DAOType(type = DAO.MODE.STATELESS)
private DAO<JPAObject> dao;
@Test
public void testMutipleRoots() throws Exception {
TNode root;
root = new TNode("A1");
root.add(new TNode("A11"));
dao.saveOrUpdate(root);
root = new TNode("B1");
root.add(new TNode("B11"));
dao.saveOrUpdate(root);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在阅读了一些有关 JPQL 的内容后,我自己找到了一个解决方案。
(子)查询解决了这个问题:
I found a solution by myself after reading a little bit about JPQL.
The (Sub-) Query solves the problem: