Как использовать @NamedQuery весной CrudRepository @Query?

Я хочу использовать @NamedQuery внутри 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";
}

результат:

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

обновление:

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 {

}

все же исключение:

PropertyReferenceException: No property findAllCustom found for type MyEntity!

1 ответов


посмотри документация Spring Data JPA-использование JPA NamedQueries.

я советую вам следовать соглашениям, установленным в документации (начиная с простого имени настроенного класса домена, за которым следует имя метода, разделенное точкой). Вырежьте подчеркивание и назовите запрос как

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

или даже лучше добавить наводящее имя, как findByAge или sth.

чтобы разрешить выполнение этих именованных запросов все вам нужно сделать это, чтобы указать MyEntityRepository следующим образом:

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

я реализовал его с помощью JpaRepository как показано в документации. Но вы можете попробовать с помощью простого CrudRepository и посмотреть, если это работает.

Я думаю, проблема была в том, что вы использовали @Query и запросы, аннотированные к методу запроса, будут иметь приоритет над запросами, определенными с помощью @NamedQuery. Читать документы для использования @Query, я думаю, вы также используете его неправильный.


обновление Чтобы использовать Pageable, по данным ответ

чтобы применить разбиение на страницы, должен быть получен второй подзапрос. Потому что подзапрос ссылается на те же поля, вам нужно убедиться, что ваш запрос использует псевдонимы для сущностей / таблиц, на которые он ссылается

это означает, что вы перепишите свой запрос query ="select * from MyEntity me where me.age >= 18".

пример использовался для @Query, но это также именованный запрос, поэтому он должен применяться и к вашему случаю. Разница только в том, что с @Query вы фактически связываете их напрямую, а не аннотируете их к классу домена.


обновление 2

я попробовал в своем собственном приложении. Во-первых, вы должны иметь запрос, используя псевдоним вместо * (i.e me). Во-вторых, строка, которую вы используете FIND_ALL_CUSTOM не следует конвенции, которая "MyEntity.findAllCustom".

решение

копировать вставить это:

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";
}

как будет работать. Для того, у кого аргумент pageable method вызывает его как myEntityRepository.allCustom(new PageRequest(0,20)). Ofc, вы знаете, что myEntityRepository вводят.