You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA/Hibernate复用JPQL查询方案咨询(Quarkus Panache环境)

解决方案

针对你的需求,完全可以复用现有权限校验逻辑,不需要强制切换到Criteria查询,结合Quarkus Panache的特性,有以下几种可行方案:

1. 基于PanacheQuery的复用方案

利用Panache的查询拼接能力,把权限校验的NamedQuery作为基础,动态添加搜索条件:

步骤1:定义包含权限逻辑的基础NamedQuery

先把权限校验的WHERE条件封装成一个基础NamedQuery(比如命名为Employee.withAccessPermissions),只保留权限相关的条件,不包含搜索或ID查询的部分:

@Entity
@NamedQuery(name = "Employee.withAccessPermissions", 
            query = "SELECT e FROM Employee e " +
                    "JOIN Company c ON c.id = e.companyId " +
                    "WHERE EXISTS (" +
                    "   SELECT 1 FROM User u " +
                    "   WHERE u.companyId = c.id AND u.id = :currentUserId" +
                    ") OR EXISTS (" +
                    "   SELECT 1 FROM Cooperation co " +
                    "   WHERE (co.companyAId = :userCompanyId AND co.companyBId = c.id) " +
                    "   OR (co.companyBId = :userCompanyId AND co.companyAId = c.id)" +
                    ")")
class Employee extends PanacheEntityBase {
    @Id
    String id;
    LocalDate dateOfBirth;
    String companyId;
    // 关联实体根据实际逻辑补充
}

步骤2:复用基础查询实现搜索和ID查询

通过Panache的find方法或PanacheQuery的链式调用,在基础查询上动态添加条件:

实现搜索功能(companyId或dateOfBirth范围)

public PanacheQuery<Employee> searchEmployees(String currentUserId, String userCompanyId, String companyId, LocalDate startDate, LocalDate endDate) {
    PanacheQuery<Employee> query = Employee.find("#Employee.withAccessPermissions", 
                                                Parameters.with("currentUserId", currentUserId)
                                                          .and("userCompanyId", userCompanyId));
    
    // 动态添加companyId过滤
    if (companyId != null) {
        query = query.filter("companyId", companyId);
    }
    
    // 动态添加dateOfBirth范围过滤
    if (startDate != null && endDate != null) {
        query = query.filter("dateOfBirth BETWEEN ?1 AND ?2", startDate, endDate);
    }
    
    return query;
}

实现通过ID获取Employee

直接在基础查询上添加ID条件,确保权限校验被执行:

public Optional<Employee> getEmployeeById(String currentUserId, String userCompanyId, String employeeId) {
    return Employee.find("#Employee.withAccessPermissions AND e.id = :employeeId", 
                        Parameters.with("currentUserId", currentUserId)
                                  .and("userCompanyId", userCompanyId)
                                  .and("employeeId", employeeId))
                   .singleResultOptional();
}

注意:绝对不要用EntityManager.find或Employee.findById,这些方法会绕开权限校验逻辑,必须通过带权限条件的查询获取实体。

2. 封装权限校验的通用方法

如果不想每次手动拼接查询,可以封装一个通用方法统一处理权限校验:

@ApplicationScoped
public class EmployeeRepository {
    private PanacheQuery<Employee> getBasePermissionQuery(String currentUserId, String userCompanyId) {
        return Employee.find("#Employee.withAccessPermissions", 
                            Parameters.with("currentUserId", currentUserId)
                                      .and("userCompanyId", userCompanyId));
    }

    // 搜索方法
    public PanacheQuery<Employee> search(String currentUserId, String userCompanyId, String companyId, LocalDate startDate, LocalDate endDate) {
        PanacheQuery<Employee> query = getBasePermissionQuery(currentUserId, userCompanyId);
        if (companyId != null) query = query.filter("companyId", companyId);
        if (startDate != null && endDate != null) query = query.filter("dateOfBirth BETWEEN ?1 AND ?2", startDate, endDate);
        return query;
    }

    // 按ID查询
    public Optional<Employee> getById(String currentUserId, String userCompanyId, String id) {
        return getBasePermissionQuery(currentUserId, userCompanyId)
                .filter("id", id)
                .singleResultOptional();
    }
}

3. 避免遗漏权限校验的保障措施

为防止团队成员意外使用无权限校验的获取方法,可以做以下限制:

  • 将Employee类的构造函数设为包私有,仅允许通过Repository类访问
  • 对外暴露的所有实体获取方法都封装在Repository中,强制带上权限校验逻辑
  • 可选:用Quarkus CDI拦截器对EntityManager.find操作做拦截,校验是否经过权限逻辑

是否需要用Criteria查询?

不需要。Panache的NamedQuery拼接和动态过滤已经能满足需求,且比Criteria更简洁易读。只有当权限逻辑需要高度动态化(比如根据用户角色动态生成条件)时,才考虑用Criteria或Panache的PanacheQuery.from构建动态查询。


内容的提问来源于stack exchange,提问作者Werner de Groot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 07:26:01