Java 如何在 Spring 中使用 @NamedQuery 和 CrudRepository @Query?

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

How to use @NamedQuery in spring a CrudRepository @Query?

javaspringspring-dataspring-data-jpa

提问by membersound

I want to make use of a @NamedQueryinside a JpaRepository. But it does not work:

我想利用 a@NamedQuery里面的 a JpaRepository。但它不起作用:

public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
    @Query(name = MyEntity.FIND_ALL_CUSTOM)
    List<MyEntity> findAllCustom(Pageable pageable);
}

@Entity
@NamedQuery(
    name = MyEntity.FIND_ALL_CUSTOM, query = "select * from MyEntity me where me.age >= 18"
)
public class MyEntity {
    public static final String FIND_ALL_CUSTOM = "findAllCustom";
}

Result:

结果:

org.springframework.data.mapping.PropertyReferenceException: No property findAllCustom found for type MyEntity!
    at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
    at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
    at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:235)
    at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:373)
    at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:353)
    at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:84)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:61)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:94)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:205)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:72)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:369)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:192)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:225)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
    ... 28 more


Update:

更新:

public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
    List<MyEntity> findAllCustom(Pageable pageable);
}

@Entity
@NamedQuery(
    name = "MyEntity.findAllCustom", query = "select * from MyEntity me where me.age >= 18"
)
public class MyEntity {

}

Still same exception:

还是一样的例外:

PropertyReferenceException: No property findAllCustom found for type MyEntity!

采纳答案by Laurentiu L.

Take a look at the documentationof Spring Data JPA - Using JPA NamedQueries.

看看该文档春数据JPA的-使用JPA NamedQueries。

I advise you follow the conventions set in the documentation (starting with the simple name of the configured domain class, followed by the method name separated by a dot). Cut the underscore and name the query like

我建议您遵循文档中设置的约定(从配置的域类的简单名称开始,然后是用点分隔的方法名称)。剪切下划线并将查询命名为

@NamedQuery(name = "MyEntity.findAllCustom", query="...")

or even better add a suggestive name like findByAgeor sth.

或者甚至更好地添加一个暗示性的名称,如findByAge或 sth。

To allow execution of these named queries all you need to do is to specify MyEntityRepository as follows:

要允许执行这些命名查询,您需要做的就是指定 MyEntityRepository 如下:

public interface MyEntityRepository extends JpaRepository <MyEntity, Long> {
    List<MyEntity> findAllCustom();
}

I implemented it with the JpaRepositoryas the documentation exemplifies. But you could try with a simple CrudRepositoryand see if that works.

我用JpaRepository文档举例说明了它。但是你可以尝试一个简单的CrudRepository,看看是否有效。

I think the problem was you where using @Queryand the Queries annotated to the query method will take precedence over queries defined using @NamedQuery. Read the docsfor the @Query usage, i think you where also using it wrong.

我认为问题在于您使用@Query和注释到查询方法的查询将优先于使用@NamedQuery 定义的查询。阅读有关@Query 用法的文档,我认为您在何处使用它也是错误的。



Update更新使用PageablePageable, 根据this answer这个答案

to apply pagination, a second subquery must be derived. Because the subquery is referring to the same fields, you need to ensure that your query uses aliases for the entities/tables it refers to

要应用分页,必须导出第二个子查询。因为子查询引用相同的字段,所以您需要确保您的查询对其引用的实体/表使用别名

that means you would rewrite your query like query ="select * from MyEntity me where me.age >= 18".

这意味着你会像 query ="select * from MyEntity me where me.age >= 18".

The example was used for @Query, but that is also a named query so it should apply to your case as well. The only difference is that with @Queryyou actually bind them directly rather than annotating them to the domain class.

该示例用于@Query,但这也是一个命名查询,因此它也应该适用于您的情况。唯一的区别是@Query您实际上直接绑定它们而不是将它们注释到域类。



Update 2

更新 2

I tried in my own app. First off you should have the query using the alias instead of * (i.e me). Secondly the string you use FIND_ALL_CUSTOMis not following the convention which is "MyEntity.findAllCustom".

我在自己的应用程序中尝试过。首先,您应该使用别名而不是 * (即me)进行查询。其次,您使用的字符串FIND_ALL_CUSTOM不遵循“MyEntity.findAllCustom”的约定。

Solution

解决方案

Copy paste this:

复制粘贴这个:

public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
    List<MyEntity> findAllCustom(Pageable pageable);
    List<MyEntity> findAllCustom();
}

@Entity
@NamedQuery(
    name = MyEntity.FIND_ALL_CUSTOM, query = "select me from MyEntity me where me.age >= 18"
)
public class MyEntity {
    public static final String FIND_ALL_CUSTOM = "MyEntity.findAllCustom";
}

Both will work. For the one with the pageable method argument call it as myEntityRepository.allCustom(new PageRequest(0,20)). Ofc, you know that myEntityRepositoryis injected.

两者都会起作用。对于具有 pageable 方法参数的方法,将其称为myEntityRepository.allCustom(new PageRequest(0,20)). Ofc,你知道那myEntityRepository是注入。