在Spring Repository中命名查询参数

时间:2018-01-30 06:35:23

标签: java spring jpa spring-data-jpa jpql

此示例正常。

@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:参数   那个位置[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);

产生错误:

  

org.springframework.dao.InvalidDataAccessApiUsageException:名称   参数绑定不能为null或为空!在JDK上&lt; 8,你需要   使用@Param作为命名参数,在JDK 8或更高版本上,请务必使用   用-parameters编译。嵌套异常是   java.lang.IllegalArgumentException:参数绑定的名称必须   不是空或空!在JDK上&lt; 8,你需要使用@Param进行命名   参数,在JDK 8或更高版本上,请务必使用-parameters进行编译。

更新:

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

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

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

3 个答案:

答案 0 :(得分:3)

使用@Param命名参数

Spring Data查询参数根据其位置进行替换。但这可能会出错,绑定可能容易出错。因此,建议在method参数中使用@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类时,默认情况下java编译器会更改方法参数名称。假如你编译这段代码

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

你最终可能会有这个

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

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

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

进行编译

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

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

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

的简要介绍

答案 1 :(得分:1)

第一个例外是因为你写了=month而不是=:month。这样,您只有一个绑定参数,但两个方法参数不匹配。

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

  

参数绑定的名称不能为null或为空!   在JDK上&lt; 8,您需要在JDK 8或更高版本上使用@Param作为命名参数,请务必使用-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或更高版本,则可以应用错误消息中提供的其他选项:

  

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

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

有关背景信息,请参阅此问题:Why are Spring Data repository method parameters names not available even on Java 8?

答案 2 :(得分:0)

请为最后一次查询尝试此操作。

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

基于此错误

  

你需要在JDK 8或更高版本上使用@Param作为命名参数   一定要用-parameters编译。

请查看here以了解更新问题。