简体   繁体   中英

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

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

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!

Take a look at the documentation of Spring Data JPA - Using 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 findByAge or sth.

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

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

I implemented it with the JpaRepository as the documentation exemplifies. But you could try with a simple CrudRepository and see if that works.

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


Update To use the Pageable , according to 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" .

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 @Query you actually bind them directly rather than annotating them to the domain class.


Update 2

I tried in my own app. First off you should have the query using the alias instead of * (ie me ). Secondly the string you use FIND_ALL_CUSTOM is not following the convention which is "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 myEntityRepository is injected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM