Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Criteria API:在具有继承用户权限的树中查找实体_Java_Spring_Jpa_Criteria - Fatal编程技术网

Java Criteria API:在具有继承用户权限的树中查找实体

Java Criteria API:在具有继承用户权限的树中查找实体,java,spring,jpa,criteria,Java,Spring,Jpa,Criteria,我试图使用CriteriaAPI在位置的层次结构中执行相当复杂的搜索 我在这里只写相关实体及其相关属性 实体 位置 -Location-upperLocation(可能为空) -设置childrenLocation(可能为空) -设置管理器(可能为空) 警报 -源于的位置(可能为空) 使用者 更多详细信息 用户和位置之间的关系有很多种 位置表示是分层的。例如,世界是一个包含美国、英国、法国等国家的位置,这些国家本身包含城市 树中可以有无限级别的子位置 警报是否起源于某个位置 如果用户有效地(在数

我试图使用CriteriaAPI在位置的层次结构中执行相当复杂的搜索

我在这里只写相关实体及其相关属性

实体

位置
-
Location-upperLocation
(可能为空)
-
设置childrenLocation
(可能为空)
-
设置管理器
(可能为空)

警报
-
源于的位置(可能为空)

使用者

更多详细信息

用户和位置之间的关系有很多种

位置表示是分层的。例如,世界是一个包含美国、英国、法国等国家的位置,这些国家本身包含城市

树中可以有无限级别的子位置

警报是否起源于某个位置

如果用户有效地(在数据库中)管理某个位置,或者他是树中某个位置的父节点的管理者,则该用户被视为该位置的管理者。基本上,如果你是美国的经理,你会自动被认为是美国所有儿童场所的经理,以及他们的孩子,等等

我试图构建的标准必须查找源自某个位置的警报,该位置的用户要么是直接经理,要么是继承的经理

代码

我有一把刀:
AlertRepository扩展了JpaRepository,JpaSpecificationExecutor

我请求查询,只是传递规范

List alerts=dao.findAll(buildSpecificationForUser(user))

以及规范生成器:

private Specification<Alert> buildSpecificationForUser(final User user) {
        return new Specification<Alert>() {
            @Override
            public Predicate toPredicate(Root<Alert> root, CriteriaQuery<?> query, CriteriaBuilder builder) {

                query.distinct(true);

                Expression<Collection<User>> managersOfLocations = root.get("originatedIn").get("managers");
                return builder.isMember(user, managersOfLocations);
            }

        };

    }
用户专用规范BuildSpecification(最终用户){
返回新规范(){
@凌驾
公共谓词toPredicate(根根、CriteriaQuery查询、CriteriaBuilder){
query.distinct(true);
表达式managersOfLocations=root.get(“originatedIn”).get(“managers”);
返回builder.isMember(用户、管理员位置);
}
};
}
使用此功能,我只会收到用户直接管理的位置的警报

问题

如何使其在用户作为继承管理者的位置也能找到警报

更新

我也试过这个:

Join<Alert, User> managersOfLocation = root.join("originatedIn").join("upperLocation",JoinType.LEFT).join("managers",JoinType.LEFT);
return builder.equal(managersOfLocation.get("id"),user.getId());
Join managersOfLocation=root.Join(“originatedIn”).Join(“upperLocation”,JoinType.LEFT)。Join(“managers”,JoinType.LEFT); 返回builder.equal(managersOfLocation.get(“id”)、user.getId();

但是,如果用户不是任何位置的管理员,则结果集将返回所有警报事件

,因为位置的表示是分层的,所以您将需要一个来获取所需的数据。但是,中没有直接的分层查询支持。如果你希望有很多地点,你就必须这样做

如果您不会有大量的位置,或者修改表结构现在不是一个选项,那么您可以创建一个视图来执行分层SQL,并映射到该视图。例如:

如果创建以下视图
manager\u location\u all
(在PostgreSQL 9.4.4上测试):


然后,您可以使用该视图将
Set allManagers
映射添加到位置对象,然后在规范生成器中执行
root.get(“originatedIn”).get(“allManagers”)
。但是,这种方法的可扩展性不如更新数据模型。

有一个类似的问题,但还没有得到回答,不走运:非常完整的答案我会研究一下。非常感谢。
CREATE OR REPLACE VIEW manager_location_all AS
 WITH RECURSIVE ancestor_descendant(ancestor_id, descendant_id) AS (
         SELECT root.upper_location_id, root.location_id
           FROM location root
         UNION ALL
         SELECT l.upper_location_id, ad.descendant_id
           FROM location l
           JOIN ancestor_descendant ad ON l.location_id = ad.ancestor_id
        )
 SELECT manager_location.manager_id, ancestor_descendant.descendant_id AS location_id
   FROM ancestor_descendant
   JOIN manager_location ON ancestor_descendant.ancestor_id = manager_location.location_id
  UNION ALL
 SELECT manager_location.manager_id, manager_location.location_id
   FROM manager_location;