Возвращение списка проекций из пользовательского метода JpaRepository с Spring Data Rest - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть простое приложение Spring Boot с модулями Spring Data JPA и Spring Data Rest.

Spring Data Rest автоматически предоставляет репозитории JPA, но когда я отправляю HTTP-запрос GET в пользовательский метод поиска в репозитории, который возвращает список проекций, я получаю Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy117!. Когда я изменяю тип возвращаемого значения метода из списка проекций на просто проекцию, он просто отлично работает.

Персона Класс сущности

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String name;

    @Column
    private String surname;
}

Персональный репозиторий

public interface PersonRepository extends JpaRepository<Person, Long> {
    List<NameProjection> findByNameContains(@Param(value = "name") String name);
}

Прогноз

@Projection(name = "nameProjection", types = {Person.class})
public interface NameProjection {
    String getName();
}

URL: http://localhost:8080/persons/search/findByNameContains?name=a

Трассировка стека:

java.lang.IllegalArgumentException: Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy117!
    at org.springframework.data.mapping.context.PersistentEntities.lambda$getRequiredPersistentEntity$2(PersistentEntities.java:78) ~[spring-data-commons-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at java.util.Optional.orElseThrow(Optional.java:290) ~[na:1.8.0_161]
    at org.springframework.data.mapping.context.PersistentEntities.getRequiredPersistentEntity(PersistentEntities.java:77) ~[spring-data-commons-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.wrap(PersistentEntityResourceAssembler.java:72) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
    at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.toResource(PersistentEntityResourceAssembler.java:55) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
    at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.entitiesToResources(AbstractRepositoryRestController.java:110) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
    at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.toResources(AbstractRepositoryRestController.java:80) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
    at org.springframework.data.rest.webmvc.RepositorySearchController.lambda$toResource$1(RepositorySearchController.java:209) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
    at java.util.Optional.map(Optional.java:215) ~[na:1.8.0_161]
    at org.springframework.data.rest.webmvc.RepositorySearchController.toResource(RepositorySearchController.java:206) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
    at org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch(RepositorySearchController.java:190) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE]

Существует пример проекта на https://github.com/mahsumdemir/projection-demo, чтобы показать ошибку. После запуска проекта перейдите на http://localhost:8080/persons/search/findByNameContains?name=i url, и вы увидите ошибку.

UPDATE

Я хочу вернуть List<NameProjection>, потому что Spring Data JPA использует метод возвращаемого типа хранилища для определения SQL, который будет выполняться в базе данных. Вызов метода с типом возврата List<Person> выполняет select * from person; для базы данных. Но вызов метода с типом возврата List<NameProjection> выполняет select name from person; в базе данных. Дополнительные данные, собранные из базы данных, не являются проблемой в случае сущности Person. Но это большая проблема при работе с объектом, имеющим мультимедийные столбцы.

ОБНОВЛЕНИЕ 2

Проблема, связанная с jira: https://jira.spring.io/browse/DATAREST-1237

1 Ответ

0 голосов
/ 27 апреля 2018

REST Data Spring позволяет несколько проекций. И вы можете передать желаемую проекцию через URL-параметр

пример: / лиц / поиск / псевдоним? Имя = r & проекция = фамилия

так что в вашем репозитории вам не нужно перезапускать NameProjection , просто верните Person

 public interface PersonRepository extends JpaRepository<Person, Long> {
  List<Person> findByNameContains(@Param(value = "name") String name);
 }

и позвоните / people / search / findByNameContains? Name = a & projection = nameProjection и с вами все будет в порядке.

посмотрите на эту демонстрацию

...