为什么即使在 Java 8 上 Spring Data 存储库方法参数名称也不可用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40526925/
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 05:17:50  来源:igfitidea点击:

Why are Spring Data repository method parameters names not available even on Java 8?

javaspringannotationsspring-dataspring-data-jpa

提问by Adam

I'm having a hard time getting the tests to pass on Pivotal's example project for the spring-boot1.4 release from their exampleswhich shows spring-data-jpausing unannotatednamed parameters in its JPQL

我很难让测试通过 Pivotal 的spring-boot1.4 版本示例项目从他们的示例spring-data-jpa通过,这些示例显示在其 JPQL 中使用未注释的命名参数

e.g.

例如

from example.springdata.jpa.simple.SimpleUserRepository

 @Query("select u from User u where u.firstname = :firstname")
 List<User> findByFirstname(String firstname);

来自example.springdata.jpa.simple.SimpleUserRepository

 @Query("select u from User u where u.firstname = :firstname")
 List<User> findByFirstname(String firstname);

NBit is not using the @Paramannotation

注意它没有使用@Param注释

This doesn't run on my machine. I get the exception detailed here, which is self-explanatory from the title.

这不在我的机器上运行。我在这里详细说明了例外情况,从标题中可以看出这一点。

Name for parameter binding must not be null or empty! For named parameters you need to use @Param for query method parameters on Java versions

参数绑定的名称不能为 null 或为空!对于命名参数,您需要在 Java 版本上使用 @Param 查询方法参数

So I have to do this instead:

所以我必须这样做:

@Query("select u from User u where u.firstname = ?1")
List<User> findByFirstname(String firstname);

or this:

或这个:

@Query("select u from User u where u.firstname = :firstname")
List<User> findByFirstname(@Param("firstname") String firstname);

What I'm using:

我在用什么:

  • OS - Win7
  • Java - 1.8.0_112
  • IDE - Intellij IDEA 2016.2
  • JPA version - JPA v2.0
  • configuration - spring-boot-1.4.1
  • 操作系统 - Win7
  • Java - 1.8.0_112
  • IDE - Intellij IDEA 2016.2
  • JPA 版本 - JPA v2.0
  • 配置 - spring-boot-1.4.1

So have I got something wrong the way I set up the examples?

那么我设置示例的方式有问题吗?

Did spring-data-jpainclude some cool feature at one time to auto-detect param names that for some reason got removed later?

是否spring-data-jpa曾经包含一些很酷的功能来自动检测由于某种原因后来被删除的参数名称?

org.springframework.dao.InvalidDataAccessApiUsageException: Name for parameter binding must not be null or empty! For named parameters you need to use @Param for query method parameters on Java versions < 8.; nested exception is java.lang.IllegalArgumentException: Name for parameter binding must not be null or empty! For named parameters you need to use @Param for query method parameters on Java versions < 8.

    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:384)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy75.findByFirstnameOrLastname(Unknown Source)

    at example.springdata.jpa.simple.SimpleUserRepositoryTests.findByFirstnameOrLastname(SimpleUserRepositoryTests.java:86)
      ====================================================================================================================
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access##代码##0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

回答by Oliver Drotbohm

By default, interfaces do not retain parameter name information — in no Java version, even not with the debugflag set. Java 8 however added a feature to enable the retention of parameter information for all types through a new -parameterscompiler flag that needs to be set explicitly.

默认情况下,接口不保留参数名称信息——在没有 Java 版本中,即使没有debug设置标志。然而,Java 8 添加了一项功能,可以通过-parameters需要显式设置的新编译器标志来保留所有类型的参数信息。

See an exampleof this in the Spring Data examples repository.

一个例子在Spring数据实例库这一点。