1

我有这个在数据库中构建树的对象。每个节点都指向其父节点,或者为空。我需要这种关系是双向的,所以每个节点也知道它的子节点。当一个节点被删除时,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 子句。

注释此类的正确方法是什么,以便孩子只加载活跃的孩子?

孩子们是否延迟加载有关系吗?

*请注意,我正在寻找答案。

例如,这个问题似乎是相关的,但解决方案不起作用。我相信它是不同的,因为我的加入是自我引用的......但这可能是由于我缺少其他东西。用于过滤 @OneToMany 关联结果的注释

4

1 回答 1

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();
}

有几种方法可以做到这一点,我希望这个解释可以帮助你。

干杯,

于 2013-03-29T23:03:30.887 回答