【问题标题】:Naming query parameters in Spring Repository [duplicate]在 Spring Repository 中命名查询参数 [重复]
【发布时间】:2018-07-08 23:28:04
【问题描述】:

这个例子运行良好。

@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:名称为 参数绑定不能为空或空!在 JDK

更新:

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

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

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

【问题讨论】:

  • YEAR(t.date) =:ear") 拼写错误?
  • good eye krezus(我在帖子中拼错了,在代码中一切都很好)

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


【解决方案1】:

使用@Param 的命名参数

Spring Data 查询参数根据它们的位置被替换。但这可能会出错,并且绑定可能容易出错。因此建议在方法参数中使用@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的简要想法

【讨论】:

    【解决方案2】:

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

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

    参数绑定的名称不能为空或空! 在 JDK

    像这样:

    @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?

    【讨论】:

    • 我在你回答的同时更新了我的答案。我用jdk8。这意味着我不需要添加@Param 还是我错了?
    • 更新了答案
    【解决方案3】:

    请在最后一次查询时试试这个。

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

    基于这个错误

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

    请查看here 了解您的更新问题。

    【讨论】:

    • 我同时更新了帖子。是的,它适用于@Param,但我使用的是 JDK 8,所以它应该被删除。
    • 检查here。你的问题已经有了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    • 2017-01-08
    • 2019-03-08
    • 1970-01-01
    • 2019-12-23
    • 2020-04-16
    • 1970-01-01
    相关资源
    最近更新 更多