Jpa递归查询

时间:2014-05-02 14:07:51

标签: java jpa eclipselink

考虑以下架构

@Entity
Class employee{

@OneToMany()
List<employee> manaagedEmps;
@OneToOne
employee manager;

}

如何编写一个查询,以获取某个经理,直接(managedEmps列表)和间接(由托管员工管理)的所有托管员工。

4 个答案:

答案 0 :(得分:3)

似乎JPA不支持递归查询。最近我通过添加ltree (postgresql)类型的“路径”字段解决了这个问题。通过将由dot分隔的id添加到父路径来生成路径,并且根节点的路径只是id。使用该字段,您可以查询某个节点(经理)的子树(直接和间接员工):

SELECT * FROM nodes WHERE path ~ '*.42.*{1,}'; /* for path of type ltree */
SELECT * FROM nodes WHERE path LIKE '%.42.%'; /* for path of type varchar */

以下JPQL查询返回ID为2的员工的平面子列表。

        List<Employee> subs = em.createQuery(
            "SELECT e FROM Employee e LEFT JOIN FETCH e.subs WHERE e.path LIKE '%.' || ?1 || '.%'",
            Employee.class
    ).setParameter(1, '2').getResultList();

答案 1 :(得分:1)

我通常更喜欢提供一些代码,但在这种情况下,我认为the article本身可以更好地解释。

答案 2 :(得分:1)

//Returns a list of the managed employee of the manager with the specified ID.
@NamedQuery(name="queryName", query="SELECT p.managedEmps FROM employee p WHERE p.manager.uuid = :uuid")

答案 3 :(得分:0)

我在这里使用postgresql。

我是通过这样的本地查询来做到这一点的:

假设以下实体

@Entity
@Table(name = "employee")
public class Employee {
 @Id
 private Long id;
 @ManyToOne
 @JoinColumn(name = "parent_id")
 private Employee parent;
}

现在,以下查询可用于递归地将一个管理器下的所有子级和子级:

public interface IEmployeeRepository extends JpaRepository<Employee, Long> {
  @Query(value = "with recursive subordinates as ("
   + " select e1.id as id, e1.parent_id as parent from employee e1 where e1.parent_id = :parentId"
   + " union"
   + " select e2.id, e2.parent_id from employee e2"
   + " inner join subordinates s on (s.id = e2.parent_id)"
   + " ) select * from subordinates", nativeQuery = true)
  Collection<Employee2> getChilds(@Param("parentId") Long parentId);
  public static interface Employee2 {
    Long getId();
    Long getParent();
  }
}

现在,您必须将此结果Collection转换为服务层中的List。而已。

参考: postgres recursive queries Jpa Projections to get result

希望这会有所帮助。