在 Spring 存储库中命名查询参数

Naming query parameters in Spring Repository

这个例子工作正常。

@Query("select t from TimeTable t where MONTH(t.date) = ?1 and YEAR(t.date) = ?2")
List<TimeTable> findAll(Integer month, Integer year);

现在我尝试将 ?1 和 ?2 替换为如下名称

@Query("select t from TimeTable t where MONTH(t.date) =month and YEAR(t.date) =:year")
List<TimeTable> findAll(Integer month, Integer year);

这个不起作用并产生错误:

org.springframework.dao.InvalidDataAccessApiUsageException: Parameter with that position [1] did not exist; nested exception is java.lang.IllegalArgumentException: Parameter with that position [1] did not exist

还有这个

@Query("select t from TimeTable t where MONTH(t.date) =:month and YEAR(t.date) =:year")
List<TimeTable> findAll(Integer month, Integer year);

产生错误:

org.springframework.dao.InvalidDataAccessApiUsageException: Name for parameter binding must not be null or empty! On JDKs < 8, you need to use @Param for named parameters, on JDK 8 or better, be sure to compile with -parameters.; nested exception is java.lang.IllegalArgumentException: Name for parameter binding must not be null or empty! On JDKs < 8, you need to use @Param for named parameters, on JDK 8 or better, be sure to compile with -parameters.

更新:

就像上面的错误说我不需要在 JDK 8 上使用 @Param,但是使用 @Param 的解决方案有效:

List<TimeTable> findAll(@Param("month") Integer month, @Param("year") Integer year);

当我删除@Params 时,它再次出现此错误。

请在最后一个查询中尝试这个。

 List<TimeTable> findAll(@Param("month") Integer month, @Param("year") Integer year); 

基于此错误:

you need to use @Param for named parameters, on JDK 8 or better, be sure to compile with -parameters.

请检查 了解您的更新问题。

第一个异常发生是因为您写了 =month 而不是 =:month。这样你只有一个绑定参数但是两个不匹配的方法参数。

在第二种情况下,您的字节代码不包含有关参数名称的信息。只做异常告诉你做的事:

Name for parameter binding must not be null or empty! On JDKs < 8, you need to use @Param for named parameters, on JDK 8 or better, be sure to compile with -parameters.

像这样:

@Query("select t from TimeTable t where MONTH(t.date) =:month and YEAR(t.date) =:year")
List<TimeTable> findAll(@Param("month") Integer month, @Param("year") Integer year);

如果您使用 Java 8 或更高版本,您可以应用错误消息中给出的其他选项:

on JDK 8 or better, be sure to compile with -parameters

如果您这样做,则不需要 @Param 注释。

查看此问题了解背景:

使用@Param 命名参数

Spring 数据查询参数根据位置替换。但这可能会出错并且绑定可能容易出错。因此建议在方法参数中使用@Param注解来绑定查询参数名。并且在查询中需要用:paramName来表示同样的paramName是要和方法参数绑定

如下更新您的方法

@Query("select t from TimeTable t where MONTH(t.date) =:month and YEAR(t.date) =:year")
List<TimeTable> findAll(@Param("month") Integer month, @Param("year") Integer year);

根本无法保留接口的方法参数名称

编译 java class 时,默认情况下 java 编译器会更改方法参数名称。假设你编译这段代码

public class Foo {
  public void bar(int myHolyParam) {}
}

你最终可能会得到这个

public class Foo {
  public void bar(int arg0) {}
}

您的参数名称已丢失。您可以通过设置像 -g:vars 这样的编译器标志来保留名称,但这只会对您的 类 有所帮助。接口方法参数名不能保留。在 JDK 8 次罢工之前,没有合法的方法来帮助这个案子。你可以在这方面看到这个SO Question

on JDK 8 或更好,一定要用 -parameters

编译

最近JDK8提出了解决方案。如果您想保留方法参数名称(对于 类 或接口),您可以通过设置 -parameter 标志简单地告诉编译器。利用此 JDK 8 功能,Spring 可以使用反射推导出参数名称。但请记住,您仍然需要使用编译器标志 -parameters 才能拥有此功能。

因此,如果您不使用该标志或使用 java 小于 8 的版本,则必须使用 @Param 注释来标记您的参数。

您可以阅读有关 Named Parameter in Java 8

的简要想法