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

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日