Как добавить пользовательские методы в Spring Data Rest JPA и использовать поддержку HATEOS?

У меня есть контроллер хранилища данных Spring, который использует JPA для реализации запроса, и мне нужно добавить некоторые настраиваемые методы запросов, которые невозможно выполнить с помощью стандартного метода queryByExample, поддерживаемого JPA. Я создал класс Impl, который имеет необходимый метод, но я не могу его распознать. Я видел, что я могу использовать стандартный MVC-контроллер Spring, но я хочу иметь унифицированный API, и в основном все, что мне действительно нужно, - это реализовать собственные методы поиска/поиска.

Даже с настраиваемым контроллером проблема заключается в том, что ссылки HAL и другие связанные элементы больше не предоставляются.

Могут ли люди Spring потратить некоторое время на то, чтобы кто-то документировал, как сделать некоторые из этих более продвинутых вещей? Я предполагаю, что необходимость реализовать свои собственные методы поиска порой довольно распространены, и было бы хорошо потрачено, чтобы дать понять, как это сделать.

Ответ 1

Простая реализация может выглядеть так:

@BasePathAwareController
class CustomInvocationsController implements ResourceProcessor<RepositorySearchesResource> {

  private final YourRepository repository;

  public CustomInvocationsController(YourRepository repository) {
    this.repository = repository;
  }

  @RequestMapping(…)
  ResponseEntity<?> handleRequest(PersistentEntityResourceAssembler assembler)

    // invoke repository
    // Use assembler to build a representation
    // return ResponseEntity
  }

  @Override
  public RepositorySearchesResource process(RepositorySearchesResource resource) {
    // add Link to point to the custom handler method
  }
}

Несколько замечаний:

  • используя @BasePathAwareController вместо простого @Controller, убедитесь, что все, к чему вы привязываете метод обработчика, рассмотрит базовый путь, который вы настроили на Spring Data REST. тоже.
  • в рамках сопоставления запросов используйте все, что вы уже знаете из Spring MVC, выберите соответствующий HTTP-метод.
  • PersistentEntityResourceAssembler в основном абстрагирует настройку модели представления в пределах PersistentEntityResource, чтобы Spring Data REST определял специфику лечения ассоциаций и т.д. (ассоциации становятся ссылками и т.д.
  • реализовать ResourceProcessor для последующей обработки RepositorySearchesResource, которая возвращается для рендеринга всех поисковых запросов. В настоящее время нет способа определить, какой тип домена был предоставлен ресурсом. Я исправил и зафиксировал DATAREST-515, чтобы улучшить это.

Ответ 2

Хорошо, основываясь на информации, представленной до сих пор, у меня есть что-то работающее, которое, я думаю, имеет смысл. Я определенно ищу кого-то, кто бы подтвердил мои теории до сих пор.

Цель заключалась в том, чтобы иметь возможность реализовать дополнительные пользовательские методы для методов, которые SDR уже предоставляет. Это связано с тем, что мне нужно реализовать дополнительную логику, которая не может быть выражена в виде простых методов запросов (Data Search Repository) (методы findByXXX). В этом случае я хочу запросить другие источники данных, такие как Solr, а также обеспечить пользовательскую манипуляцию данными до их возврата.

Я реализовал контроллер, основанный на том, что предложил @oliver, следующим образом:

@BasePathAwareController
@RequestMapping(value = "/persons/search")
public class PersonController implements ResourceProcessor<RepositorySearchesResource>, ResourceAssembler<Person, Resource<Person>> {

    @Autowired
    private PersonRepository repository;

    @Autowired
    private EntityLinks entityLinks;

    @RequestMapping(value = "/lookup", method = RequestMethod.GET)
    public ResponseEntity<Resource<Person>> lookup(@RequestParam("name") String name)
    {
        try
        {
          Resource<Person> resource = toResource(repository.lookup(name));
          return new ResponseEntity<Resource<Person>>(resource, HttpStatus.OK);
        }
        catch (PersonNotFoundException nfe)
        {
            return new ResponseEntity<Resource<Person>>(HttpStatus.OK);
        }
    }

    @Override
    public RepositorySearchesResource process(RepositorySearchesResource resource) {

        LinkBuilder lb = entityLinks.linkFor(Person.class, "name");
        resource.add(new Link(lb.toString() + "/search/lookup{?name}", "lookup"));
        return resource;
    }

    @Override
    public Resource<Person> toResource(Person person) {
        Resource<IpMaster> resource = new Resource<Person>(person);

        return resource;
    }

Это создает метод поиска, который считается шаблоном и указан, когда вы выполняете запрос на /persons/search, а также другие методы поиска, определенные в Repository. Он не использует предложенный PersistentEntityResourceAssembler. Я думаю, что я предпочел бы использовать это, но потом я немного смущен относительно того, как его вводить, и что означает комментарий об ошибке.

Ответ 3

См. последние документы, так как самая последняя версия SDR содержит более подробную информацию об этом и делает ее немного проще. Ключ должен использовать аннотацию @RepositoryRestController, чтобы иметь возможность добавлять дополнительные методы в конце конечной точки /search или аннотации @BasePathAwareController, если вы хотите добавить конечные точки в другие части пространства имен URL. Затем включите PersistentEntityResourceAssembler в качестве параметра в свой метод контроллера и используйте его для генерации вывода HAL, если вы возвращаете объекты объекта.