有没有一种方法可以直接使用HibernateFilter注入查询?

时间:2020-04-01 07:43:28

标签: java hibernate

我需要设置一个更复杂的休眠过滤器,该过滤器由可能缺少的多个参数组成。基本上,我希望我的过滤器注入类似:

shipmentIds in (...) AND cityIds in (....) AND countryIds in (....)

在某些情况下,我可能只有 shipmentIds ,而注入的查询只能是

shipmentIds in (...)

并且由于我的过滤器需要根据我可以提供的ID进行动态调整,因此我尝试执行以下操作,但失败了:

    @FilterDefs({
        @FilterDef(name = CUSTOM_FILTER,
                    parameters = { @ParamDef(name = CUSTOM_QUERY, type = "string")})
    })
    @Filters({
        @Filter(name = CUSTOM_FILTER, condition =  " :"+ CUSTOM_QUERY +" ")
    })
    public class MyClass { ... }

我的过滤器逻辑:

org.hibernate.Filter filter = entityManager.unwrap(Session.class).enableFilter(CUSTOM_FILTER);
//customQuery contains the condition that I need to inject
filter.setParameter(CUSTOM_QUERY, customQuery); 
filter.validate();

我得到的例外是这个:

org.postgresql.util.PSQLException: ERROR: argument of AND must be type boolean, not type character varying_

我怀疑这是由于我的过滤器使用的 type =“ string” 造成的。那是使用来自休眠的StringType,它用逗号将查询换行:

return '\'' + value + '\'';  

那么有没有一种方法可以动态地注入这样的查询,或者我应该为id之间的每个组合定义多个自定义过滤器?

1 个答案:

答案 0 :(得分:0)

我终于设法找到了解决此问题的方法,因此我将在此处添加答案。

那么有没有一种方法可以动态地注入这样的查询,或者我应该为id之间的每个组合定义多个自定义过滤器?

这里的解决方案不是动态插入单个查询,因为它仍然不可行,而是定义多个过滤器,而不是为每个组合定义自定义过滤器,而是为每个过滤器定义简单过滤器。接下来,我们基本上激活我们需要的任何一个,这样,最终查询将具有可提供的ID子句。

代码看起来像这样:

public void applyFiltering() {
    // ... rest of the code to retrieve the set of ids
    createFilterFor(cityIds, CITY_FILTER, CITY_IDS_PARAM);
    createFilterFor(countryIds, COUNTRY_FILTER, COUNTRY_IDS_PARAM);
    createFilterFor(shipmentIds, SHIPMENT_FILTER, SHIPMENT_IDS_PARAM);
}

private void createFilterFor(final Set<Long> ids, final String filterName, final String paramName) {
    if(CollectionUtils.isNotEmpty(ids)) {
        org.hibernate.Filter filter = entityManager.unwrap(Session.class).enableFilter(filterName);
        filter.setParameterList(paramName, ids);
        filter.validate();
    }
}

注意 CITY_FILTER,CITY_IDS_PARAM 等只是用于正确加载过滤器的普通唯一常量字符串。

过滤逻辑:

shipmentIds in (...) AND cityIds in (....) AND countryIds in (....)

使用上述方法,最终查询可能会遇到其他条件,例如

shipmentIds in (...) AND cityIds in (....)

@Action(LoadSummary)
  LoadSummary({ patchState, dispatch }: StateContext<StateModel>, { id }: LoadSummary) {
    this.detailService.getSummary(id).subscribe((response) => {
      patchState({
        summary: response?.data
      });
      // dispatch success action
      dispatch(new LoadSummarySuccess());
    });
  }

或只是个人。