[英]Trying to add filter to hibernate self-referencing OneToMany join
I have this object that builds a tree in the database. 我有一个在数据库中构建树的对象。 Each node points to its parent, or is null.
每个节点都指向其父节点,或者为null。 I need this relationship to be bi-directional, so each node also knows its children nodes.
我需要这种关系是双向的,因此每个节点也都知道其子节点。 When a node is deleted IS_ACTIVE gets set to false.
删除节点后,IS_ACTIVE设置为false。 How do I modify these annotations such that only children with IS_ACTIVE set to true get loaded?
如何修改这些注释,以便仅将IS_ACTIVE设置为true的子级加载?
@Entity
@Table(name = "node")
public class Node {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_NODE_ID")
private Node parentNode;
@OneToMany(mappedBy = "parentNode", fetch = FetchType.LAZY)
private Set<Node> childrenNodes;
@Column(name = "IS_ACTIVE", nullable = false)
private boolean isActive;
//other fields that shouldn't matter left out.
}
Currently my unit tests are running in the same transaction, so I have to use session.refresh(node) to get the children nodes to load at all, but every time it loads all of the children ignoring my filters and where clause. 当前,我的单元测试正在同一事务中运行,因此我必须使用session.refresh(node)来完全加载子节点,但是每次加载所有子节点时,都会忽略我的过滤器和where子句。
What is the correct way to annotate this class so the children only the active children load? 给班级添加注释的正确方法是什么?
Does it matter if the children are lazy-loaded? 孩子是否懒惰有关系吗?
*Please note I have search for answers to this. *请注意,我正在寻找答案。
As an example, this question seems related, but the solution does not work. 例如,这个问题似乎相关,但是解决方案不起作用。 I belive it is different because my join is self-referencing... but it might be due to something else I am missing.
我相信这是不一样的,因为我的加入是自我引用的...但是这可能是由于我缺少了其他原因。 annotation to filter results of a @OneToMany association
注释以过滤@OneToMany关联的结果
When you say "only children with IS_ACTIVE set to true get loaded", you are defining a business rule and therefore you have to instruct Hibernate to follow it somehow. 当您说“仅将IS_ACTIVE设置为true的子代加载”时,您正在定义业务规则,因此必须指示Hibernate以某种方式遵循它。
Using "session.get(object)" and "session.refresh(object)" you are asking Hibernate to get an Entity, however you did not instruct Hibernate to follow your business rule. 您正在使用“ session.get(对象)”和“ session.refresh(对象)”要求Hibernate获取实体,但是您并未指示Hibernate遵循您的业务规则。
Briefly speaking, there are two ways to solve your issue: 简而言之,有两种方法可以解决您的问题:
(1): Let Hibernate fetch all "childrenNodes", subsequently you can write another method to return only children with IS_ACTIVE = true. (1):让Hibernate提取所有“ childrenNodes”,随后您可以编写另一种方法以仅返回IS_ACTIVE = true的子代。 Something like:
就像是:
public Set<Node> getActiveChildrenNodes(Node n){
Set<Node> result = new HashSet();
for(Node cn : n.getChildrenNodes()){
if(cn.isActive)
result.add(cn);
}
return result;
}
As you may see, this approach may have a bad performance if you have several records in your database. 如您所见,如果您的数据库中有多个记录,则这种方法的性能可能很差。
(2): A better options would be to load only children with IS_ACTIVE = true. (2):更好的选择是仅加载IS_ACTIVE = true的子级。 So, you can write something like:
因此,您可以编写如下内容:
public List getActiveChildrenNodes(Node n, Session s){
return = session
.createQuery("FROM Node WHERE Node.id = :pId AND Node.childrenNodes.isActive : pIsActive")
.setParameter("pId", n.getId())
.setParameter("pIsActive", true)
.list();
}
There are several ways to do it, I hope this explanation can help you. 有几种方法可以实现,希望此说明对您有所帮助。
Cheers, 干杯,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.