我有这个对象在数据库中构建一个树。每个节点都指向其父节点,或者为null。我需要这种关系是双向的,因此每个节点也知道它的子节点。删除节点时,IS_ACTIVE设置为false。如何修改这些注释,以便只有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.
}
目前我的单元测试在同一个事务中运行,所以我必须使用session.refresh(node)来获取子节点才能加载,但每次加载所有子节点时忽略我的过滤器和where子句
注释此类的正确方法是什么,以便只有活动子项加载的子项?
孩子们是否懒惰是否重要?
*请注意我已经找到了答案。
举个例子,这个问题似乎有关系,但解决方案不起作用。我相信它是不同的,因为我的加入是自我引用...但它可能是由于我缺少的其他东西。 annotation to filter results of a @OneToMany association
答案 0 :(得分:1)
当你说“只有IS_ACTIVE设置为true的孩子被加载”时,你正在定义一个业务规则,因此你必须指示Hibernate以某种方式遵循它。
使用“session.get(object)”和“session.refresh(object)”你要求Hibernate获得一个实体,但是你并没有指示Hibernate遵循你的业务规则。
简而言之,有两种方法可以解决您的问题:
(1):让Hibernate获取所有“childrenNodes”,然后你可以编写另一个方法来只返回IS_ACTIVE = true的子节点。类似的东西:
public Set<Node> getActiveChildrenNodes(Node n){
Set<Node> result = new HashSet();
for(Node cn : n.getChildrenNodes()){
if(cn.isActive)
result.add(cn);
}
return result;
}
正如您所看到的,如果您的数据库中有多条记录,这种方法的性能可能会很差。
(2):更好的选择是仅加载IS_ACTIVE = true的孩子。所以,你可以这样写:
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();
}
有几种方法可以做到,我希望这个解释可以帮到你。
干杯,