大黄瓜de冬天 2024-02-05 09:30 采纳率: 88.9%
浏览 3
已结题

Aspect过滤器怎么控制让他失效

我的项目有一个AfterReturning,它对一个字段进行了过滤,但是当我本身查询带有该字段时,会导致有2个该字段的条件,从而查不到数据。我希望当查询条件有该字段时它是失效的。我想到了查询sql时写or,但不是一个完美的解决办法。我希望的结果是写一个前置过滤器或者在afterOpenSession判断操作的查询参数中是否含有该字段,有时把afterOpenSession的设置跳过


@Aspect
public class TenantFilterAspect {

    @Pointcut("execution (* org.hibernate.internal.SessionFactoryImpl.SessionBuilderImpl.openSession(..))")
    public void openSession() {
    }



    @AfterReturning(pointcut = "openSession()", returning = "session")
    public void afterOpenSession(Object session) {
        if (session instanceof Session) {
            String tenantId = LoginHelper.getTenantId();
            String dynamic = TenantHelper.getDynamic();
            if (StringUtils.isNotBlank(dynamic)) {
                tenantId = dynamic;
            }
            if (tenantId != null && !tenantId.equals("000000")) {
                LoginUser loginUser = LoginHelper.getLoginUser();
                List<String> subTenantIds = loginUser.getSubTenantIds();
                //无子租户创建一个新的集合添加本身租户编号去过滤数据
                if(subTenantIds == null)
                    subTenantIds = new LinkedList<>();
                subTenantIds.add(tenantId);
                org.hibernate.Filter filterList = ((Session) session).enableFilter("tenantListFilter");
                filterList.setParameterList("tenantId", subTenantIds);

                org.hibernate.Filter filter = ((Session) session).enableFilter("tenantFilter");
                filter.setParameter("tenantId", tenantId);
            }
        }
    }

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-02-05 09:31
    关注

    引自免费微信小程序:皆我百晓生

    为了实现当查询条件中已包含特定字段时,让TenantFilterAspect中的过滤器失效,你可以通过在afterOpenSession方法中检查查询参数来判断是否需要启用过滤器。以下是一个修改后的示例:

    @Aspect
    public class TenantFilterAspect {
    
        @Pointcut("execution (* org.hibernate.internal.SessionFactoryImpl.SessionBuilderImpl.openSession(..))")
        public void openSession() {
        }
    
        @Around("openSession()")
        public Object applyTenantFilterIfNeeded(ProceedingJoinPoint pjp) throws Throwable {
            // 获取原始的Session对象
            Session session = (Session) pjp.proceed();
    
            if (session != null) {
                String tenantId = LoginHelper.getTenantId();
                String dynamic = TenantHelper.getDynamic();
                if (StringUtils.isNotBlank(dynamic)) {
                    tenantId = dynamic;
                }
                
                // 检查当前执行的方法是否带有查询参数(这里假设是Hibernate Criteria或Query对象)
                boolean shouldSkipFilter = false;
                Object[] args = pjp.getArgs();
                for (Object arg : args) {
                    // 根据你的具体场景调整此处逻辑,例如针对Criteria、Query或NativeQuery等对象进行检查
                    if (arg instanceof Criteria || arg instanceof Query) {
                        // 假设我们能从查询对象中获取到用于检查的属性名(这里是示例,请替换为实际的属性名称)
                        String filterField = "your_field_name";
                        if (containsFilterField((org.hibernate.query.Query) arg, filterField)) {
                            shouldSkipFilter = true;
                            break;
                        }
                    }
                }
    
                if (!shouldSkipFilter && tenantId != null && !tenantId.equals("000000")) {
                    LoginUser loginUser = LoginHelper.getLoginUser();
                    List<String> subTenantIds = loginUser.getSubTenantIds();
                    if (subTenantIds == null) {
                        subTenantIds = new LinkedList<>();
                    }
                    subTenantIds.add(tenantId);
    
                    // 启用过滤器
                    org.hibernate.Filter filterList = ((Session) session).enableFilter("tenantListFilter");
                    filterList.setParameterList("tenantId", subTenantIds);
    
                    org.hibernate.Filter filter = ((Session) session).enableFilter("tenantFilter");
                    filter.setParameter("tenantId", tenantId);
                }
            }
    
            return session;
        }
    
        // 添加一个辅助方法用于检查Query对象是否包含了指定的字段作为条件
        private boolean containsFilterField(org.hibernate.query.Query query, String filterField) {
            // 这里只是示例,实际可能需要解析HQL或SQL语句以确定查询条件
            // 由于 Hibernate API 并未直接提供这样的功能,你可能需要自定义解析逻辑或查找其他方法来检查查询条件
            // 下面是一个简单的模拟检查(实际不可用):
            String queryString = query.getQueryString();
            // 示例:使用正则表达式检查HQL/SQL字符串
            return queryString.matches("(?i).*\\b" + Pattern.quote(filterField) + "\\b.*");
        }
    }
    

    请注意,上述代码中的containsFilterField方法仅作为示例,并未提供真正的实现。在实际项目中,检查查询条件是否包含特定字段通常会更复杂,因为Hibernate并未提供直接获取Query或Criteria中所有条件的方法。你可能需要根据实际情况分析查询语句或利用Hibernate的内部API来实现这一功能。

    如果你使用的不是HQL而是JPA的Specification或者Spring Data JPA的Repository接口,则可能需要在创建查询的地方进行处理,而不是在拦截openSession这个点上。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 3月8日
  • 已采纳回答 2月29日
  • 创建了问题 2月5日

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大