java 在 Spring Repository 中命名查询参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48515309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 10:05:44  来源:igfitidea点击:

Naming query parameters in Spring Repository

javaspringjpaspring-data-jpajpql

提问by degath

This example works fine.

这个例子工作正常。

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

Now I try to replace ?1 and ?2 with names like below

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

This one doesn't work and produce error:

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

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

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

And this one

还有这个

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

produce error:

产生错误:

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.

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

UPDATE:

更新:

like an error above says I do not need to use @Param on JDK 8, but solution with @Param works:

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

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

and when I delete @Params it goes this error again.

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

回答by Shafin Mahmud

Named Parameters using @Param

使用@Param 命名参数

Spring Data query parameters are replaced based on their positions. But this might go wrong and binding could be error prone. Hence it is suggested to use @Paramannotation in the method parameter to bind the query parameter names. And in the query, you need to use :paramNameto indicate that the same paramNameis to bind with the method parameter.

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

Update your method as below

更新您的方法如下

@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);

Simply its not possible to retain method parameter names for interface

根本不可能为接口保留方法参数名称

When a java class is compiled, by default java compiler changes the method parameter names. Say if you compile this code

编译 java 类时,默认情况下 java 编译器会更改方法参数名称。说如果你编译这段代码

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

You might end up having this

你可能最终会得到这个

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

Your parameter names are lost. You may retain the names by setting a compiler flag like -g:varsbut this will only help for your Classes. Interface method parameter names can not be retained. There was no legit way to help this case before JDK 8 strikes. You can see this SO Questionon this regard.

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

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

在 JDK 8 或更高版本上,一定要编译 -parameters

Lately JDK 8 comes up with the solution. If you want to retain method parameter names (for Classes or Interfaces) you can simply tell compiler by setting -parameterflag. Exploiting this JDK 8 feature, Spring can deduce the parameter names using reflection. But remember, still you need to use the compiler flag -parametersto have this ability.

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

So if you are not using that flag or using java version less than 8, you must to use @Paramannotation to mark your parameters.

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

You can read a brief idea about Named Parameter in Java 8

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

回答by Jens Schauder

The first exception happens because you wrote =monthinstead of =:month. This way you only have one bind parameter but two method arguments which doesn't match.

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

In the second case your byte code doesn't contain information about the names of the argument. Just do what the exception tells you to do:

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

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.

参数绑定的名称不能为 null 或为空!在 JDK < 8 上,您需要使用 @Param 作为命名参数,在 JDK 8 或更高版本上,请务必使用 -parameters 进行编译。

Like this:

像这样:

@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);

If you are on Java 8 or above you can apply the other option given in the error message:

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

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

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

If you do this you don't need the @Paramannotations.

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

See this question for background: Why are Spring Data repository method parameters names not available even on Java 8?

请参阅此问题的背景:为什么即使在 Java 8 上 Spring Data 存储库方法参数名称也不可用?

回答by krezus

please try this for last query.

请在最后一个查询中尝试此操作。

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

based on this error:

基于此错误

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

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

please check herefor your update question.

在此处查看您的更新问题。