在Spring Repository中命名查询参数

deg*_*ath 2 java spring jpa jpql spring-data-jpa

这个例子很好用。

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

现在我尝试用下面的名称替换?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);
Run Code Online (Sandbox Code Playgroud)

这不起作用并产生错误:

org.springframework.dao.InvalidDataAccessApiUsageException:该位置为[1]的参数不存在;嵌套异常是java.lang.IllegalArgumentException:具有该位置[1]的参数不存在

还有这个

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

产生错误:

org.springframework.dao.InvalidDataAccessApiUsageException:参数绑定的名称不能为null或为空!在JDK <8上,您需要对命名参数使用@Param,在JDK 8或更高版本上,请确保使用-parameters进行编译。嵌套异常为java.lang.IllegalArgumentException:参数绑定的名称不能为null或为空!在JDK <8上,您需要对命名参数使用@Param,在JDK 8或更高版本上,请确保使用-parameters进行编译。

更新:

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

List<TimeTable> findAll(@Param("month") Integer month, @Param("year") Integer year);
Run Code Online (Sandbox Code Playgroud)

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

Sha*_*mud 6

使用@Param的命名参数

Spring Data查询参数根据其位置进行替换。但这可能会出错,并且绑定可能容易出错。因此,建议@Param在方法参数中使用注释来绑定查询参数名称。并且在查询中,您需要使用:paramName来表示paramName要与method参数绑定。

如下更新您的方法

@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);
Run Code Online (Sandbox Code Playgroud)

只是不可能保留接口的方法参数名称

编译Java类时,默认情况下,Java编译器会更改方法参数名称。说如果您编译此代码

public class Foo {
  public void bar(int myHolyParam) {}
}
Run Code Online (Sandbox Code Playgroud)

您可能最终有这个

public class Foo {
  public void bar(int arg0) {}
}
Run Code Online (Sandbox Code Playgroud)

您的参数名称将丢失。您可以通过设置类似的编译器标志来保留名称,-g:vars但这只会对您的类有所帮助。接口方法参数名称不能保留。在JDK 8出现之前,没有合法的方法可以帮助解决此问题。您可以在这方面看到此SO 问题

在JDK 8或更高版本上,请务必使用 -parameters

最近,JDK 8提出了该解决方案。如果要保留方法参数名称(用于类或接口),只需设置-parameter标志即可告诉编译器。利用此JDK 8功能,Spring可以使用反射来推断参数名称。但是请记住,仍然需要使用编译器标志-parameters才能具有此功能。

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

您可以阅读有关Java 8中命名参数的简要说明