【问题标题】:How to check if a collection parameter is null in hql?如何检查hql中的集合参数是否为空?
【发布时间】:2018-12-24 12:27:43
【问题描述】:

那么如何在 HQL 中检查集合是否为空?简单示例:

select * from Book book where title in (:titles)

所以如果titles是一个单一的变量,我可以这样做

select * from Book book where (:titles is null or title in (:titles))

但是如果titles 是一个列表/集合呢?

select * from Book book where (:titles is null or title in (:titles))

如果titles 是一个列表,这将不起作用。经过激烈的搜索,我尝试了 is empty, size, and exists 函数,我也尝试了 (:titles) is null 选项。

以上都不起作用。我知道有一种硬编码方式可以编写不同的查询,具体取决于标题列表的状态,如果为空,则为一个查询,如果为空,则为另一个查询。但这会产生很多类似的 HQL 查询,但会有细微的变化。而且我的用例需要考虑的列表很少,因此不需要。

我的问题是甚至可以直接在 HQL 中进行检查吗?

【问题讨论】:

  • 什么是商业案例?如果您想始终获取标题等于 null 并且也等于集合中的值的数据,那么您可以执行 selct * from Book book where title in (:titles) or title is null
  • 标题不可为空,但标题列表可以为空。这个想法是根据不同的情况,有时它需要返回所有书籍,有时它应该只返回具有特定标题的某些书籍。
  • 所以你的意思是如果titles list为空那么你需要得到所有的书?在这种情况下,您应该创建两个查询:一个获取所有书籍,另一个按标题获取。并检查您的服务器代码,当列表为空且不为空时要使用哪个查询。
  • 我知道这个解决方案,但是对于我们的例子,至少会有 4 个列表,这会有很多类似的查询。如果可能的话,我想在一个查询中完成。如果没有,那么将执行多个查询。

标签: hibernate hql


【解决方案1】:

:titles 是一个列表。
您想搜索具有这些“标题”的书籍。

用户,

  • 可能选择了一个标题
  • 可能选择了多个标题
  • 或者可能根本没有选择任何标题

所以这个列表可能是空的,可能有一个或多个元素。

无论如何,您都将使用Query.setParameterList(),以便将titles 集合传递到查询中,如this answer 中所述。

现在,如果您尝试传递的参数可能为空,您就不想使用 set 方法。毕竟我们在这里讨论的是 Java。

因此,您需要检查此列表是否为空。
此外,您不希望休眠检查用户选择的标题列表是否为空。
您还只需要一个查询,不需要多个查询。

执行此操作的方法是使用查询生成器。
有很多方法可以实现这种方法。但总的来说,这个想法是你

  • 要么使用专门用于此类作业的框架,例如 Querydsl,check here
  • 或者您简单地使用 StringBuilder 来构建查询的 select、from 和 where 子句,例如:

    Map<String,Object> params = new HashMap<String,Object>();
    StringBuilder queryBuilder = new StringBuilder();
    queryBuilder.append(" from Book book ");
    if(!titlesList.isEmpty()){
        queryBuilder.append(" where book.title in (:titles) ");
        params.put("titles", titlesList);
    }
    Query query = entityManager.createQuery(queryBuilder.toString());
    for ( Map.Entry<String,Object>; param : params.entrySet()) {
        if(param instanceof Collection<?>){
            query.setParameterList(param.getKey(),param.getValue());
        }
        //if param is of type String then query.setString etc. 
        //else setParameter, you get the idea, use the docs
    }
    List<Book> results = (List<Book>) query.list();
    

【讨论】:

    猜你喜欢
    • 2010-11-09
    • 2016-03-28
    • 2011-04-15
    • 2017-05-07
    • 2018-08-09
    • 1970-01-01
    • 2011-04-24
    • 2016-06-20
    • 2017-05-28
    相关资源
    最近更新 更多