考虑以下架构
@Entity
Class employee{
@OneToMany()
List<employee> manaagedEmps;
@OneToOne
employee manager;
}
如何编写一个查询,以获取某个经理,直接(managedEmps列表)和间接(由托管员工管理)的所有托管员工。
答案 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
希望这会有所帮助。