Как добавить пользовательские методы в 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, если вы возвращаете объекты объекта.