当前位置: 首页 > 知识库问答 >
问题:

检查Spring数据JPA查询中的列表参数是否为空

邹海超
2023-03-14

我有一个Spring Boot应用程序,使用Spring Data JPA查询MySQL数据库。

我需要得到一份经过一些参数筛选的课程列表。

我通常使用语法param IS NULL或(/*对param*/)执行操作,以便在参数为NULL时忽略它。

对于简单的数据类型,我没有问题,但当涉及到对象列表时,我不知道如何检查NULLvalue。如何检查?3参数在下面的查询中是否为NULL

@Query("SELECT DISTINCT c FROM Course c\n" +
       "WHERE c.courseDate < CURRENT_TIME\n" +
       "AND (?1 IS NULL OR (c.id NOT IN (3, 4, 5)))\n" +
       "AND (?2 IS NULL OR (c.title LIKE ?2 OR c.description LIKE ?2))\n" +
       "AND ((?3) IS NULL OR (c.category IN ?3)) ")
List<Course> getCoursesFiltered(Long courseId, String filter, List<Category> categories);

错误是:

无法提取ResultSet;SQL[n/a];嵌套异常是org.hibernate.exception.DataExc0019:无法提取ResultSet[SQL:1241, 21000]

在堆栈跟踪中,我可以看到:

原因:java。sql。SQLException:操作数应包含1列

实际上,生成的查询将是。。。如果我的列表包含3个元素,则(?3、?4、?5)为空或(?3、?4、?5)中的c类)。但是为空不能应用于多个元素(如果我的列表只包含一个元素,则查询可以正常工作)。

我试过尺码(?3)


共有3个答案

周洋
2023-03-14

Spring使我们能够使用对象模型作为带有@Param注释的查询参数。另一种检查动态查询中列表类型参数是否为空的方法是在我们的搜索模型上放置getter方法。

假设您有一个名为PersonSearchFilter的搜索过滤器模型,您希望通过它来搜索Person模型;

@Query(value = "SELECT a FROM Person a WHERE 1=1 "
            + "and (:#{#searchFilter.name} is null or a.name like %:#{#searchFilter.name}%) "
            + "and (:#{#searchFilter.statusListSize} = 0 or a.status in (:#{#searchFilter.statusList})) ")
Optional<List<Person>> findByFilter(@Param("searchFilter") PersonSearchFilter searchFilter);


public class PersonSearchFilter {

    private String name;
    private List<String> statusList;
    
    public String getName() {
        return name;
    }

    public List<String> getStatusList() {
        return statusList;
    }

    public int getStatusListSize() {
        return CollectionUtils.isEmpty(statusList) ? 0:statusList.size();
    }

}
常英纵
2023-03-14

这并不能严格地回答您的问题,但一个简单的解决方案是在存储库中使用另一个方法,在调用查询之前检查列表,并将其默认为具有伪值的列表。比如:

@Query("SELECT DISTINCT c FROM Course c\n" +
       "WHERE c.courseDate < CURRENT_TIME\n" +
       "AND (?1 IS NULL OR (c.id NOT IN (3, 4, 5)))\n" +
       "AND (?2 IS NULL OR (c.title LIKE ?2 OR c.description LIKE ?2))\n" +
       "AND ('DUMMYVALUE' IN ?3 OR (c.category IN ?3)) ")
// make this private to keep it safe
private List<Course> getCoursesFiltered(Long courseId, String filter, List<Category> categories);

// public helper method to put a dummy value in the list that you can check for
public List<Course> getNullableCoursesFiltered(Long courseId, String filter, List<Category> categories) {
    if(categories == null) {
        categories = Arrays.asList("DUMMYVALUE");
    }
    return getCoursesFiltered(courseId, filter, categories);
}
宋飞掣
2023-03-14

好吧,我在半夜醒来后想到了一件事:

@Query("SELECT DISTINCT c FROM Course c\n" +
       "WHERE c.courseDate < CURRENT_TIME\n" +
       "AND (?1 IS NULL OR (c.id NOT IN (3, 4, 5)))\n" +
       "AND (?2 IS NULL OR (c.title LIKE ?2 OR c.description LIKE ?2))\n" +
       "AND (COALESCE(?3) IS NULL OR (c.category IN ?3)) ")
List<Course> getCoursesFiltered(Long courseId, String filter, List<Category> categories);

解决方案是简单地使用COALESCE除了IS NULL,所以它可以使用多个值。这样,如果列表包含至少一个非空值,第二个表达式((c.categoryIN?3))会做过滤的工作。

下次我至少要等一整晚再问问题:)

 类似资料:
  • 问题内容: 以下代码是我一直在使用的从sql数据库中检索用户信息的代码。 但是,当数据库中没有用户名等于LoginUser.Username的条目时,(dt!= null)不会返回false。有没有其他方法可以检查sqlcommand是否成功? 问题答案: 如果没有匹配的记录,您将得到一个空白,因此您可以检查返回的记录数: 并且,稍微偏离主题的地方,请阅读您的问题下方的注释,然后使用Google术

  • 我需要在JPA查询中传递这个参数。 我如何才能实现这一点,而不是为IS NULL&IS NOT NULL创建2个单独的查询。

  • 谁能告诉我@Query注释将支持数据库独立性查询机制 例子: 如果我写这个查询,它会支持所有的数据库,如Mysql、oracle、postgres。 我在spring data jpa参考文档站点中发现了类似的内容 这意味着如果我编写nativeQuery=true,它将被视为本机查询,如果不编写,它将表现为Spring data jpa特定查询,或者它将如何表现请澄清。

  • 我有3个实体在我的数据库。实体A具有主密钥PK-A,实体B具有主密钥PK-B,实体C具有主密钥PK-C。 实体A与实体B具有1对多关系,实体B与实体C具有1对多关系 我想在Spring Data JPA中基于PK-A(实际上是实体B中的外键)查询实体C。有可能吗? 但这行不通。还有什么建议我可以试试吗?

  • 问题内容: 声明使用输入参数的属性作为查询参数的Spring数据JPA查询的最简单方法是什么? 例如,假设我有一个实体类: 和另一类: …那么我想编写一个Spring数据存储库,如下所示: …但是Spring数据/ JPA不喜欢我在参数上指定属性名称。 什么是最巧妙的选择? 问题答案: 该链接将为你提供帮助:支持SpEL表达式的Spring Data JPA M1。类似的例子是:

  • 描述: 我有两张桌子,和。我想在显示员工详细信息时直接显示,但我不想配置这两个实体之间的关系(或)。 因为这将加载列的所有值,但这些值对我来说毫无用处,所以我只需要 。下面是我的代码,但它不起作用。 商店员工类型: 商店_员工: 存储库: 这可以显示<code>类型名称@Transient,它可以成功保存,但当我查询实体时,“typeName”的值为空。