Выборочное расширение ассоциаций в ответе Spring Data Rest
У меня есть стандартные настройки Spring data JPA и Spring data Rest, которые правильно возвращают ассоциации в виде ссылок на правильные ресурсы.
{
"id": 1,
"version": 2,
"date": "2011-11-22",
"description": "XPTO",
"_links": {
"self": {
"href": "http://localhost:8000/api/domain/1"
},
"otherDomain": {
"href": "http://localhost:8000/api/domain/1/otherDomain"
}
}
}
Однако в некоторых запросах я хотел бы расширить связь с "другим доменом" (чтобы клиент не выполнял N+1 запросов для получения полных данных).
Можно ли настроить Spring Data Rest для обработки ответа таким образом?
2 ответа
Ответы по умолчанию должны остаться прежними, чтобы убедиться, что полезные данные для PUT
запросы симметричны GET
с возвращением. Однако Spring Data REST представляет функцию, называемую проекциями (см. Билет JIRA), которая работает следующим образом:
Вы создаете выделенный интерфейс и добавляете все свойства, которые хотите включить в ответ:
public interface MyProjection {
String getMyProperty();
MyRelatedObject getOtherDomain();
}
Вы также можете
- аннотировать интерфейс с помощью
@Projection
и поместите его в тот же пакет, что и тип домена или его подпакет - или вы вручную регистрируете проекцию, используя
RepositoryRestConfiguration
и позвонитьprojectionConfiguration().addProjection(…)
вручную (путем расширенияRepositoryRestMvcConfiguration
и переопределениеconfigureRepositoryRestConfiguration(…)
).
Это приведет к тому, что ресурсы, выставленные для типа домена, примут projection
параметр (имя также настраивается ProjectionConfiguration
) с названием проекции. Если дано, мы пропустим рендеринг по умолчанию (который включает рендеринг ссылок на связанные сущности вместо их встраивания) и позволим Джексону рендерить прокси, поддерживающий данный интерфейс.
Пример этого также можно найти в проекте Spring RESTBucks. Увидеть OrderProjection
для определения интерфейса.
Мое решение применимо ко всем запросам, но некоторые могут посчитать его актуальным.
У меня похожая ситуация, когда в моем ответе User json вложена ассоциация userPersons, например:
{
"_embedded":{
"users":[
{
"userName":"Albert"
"userPersons":[
{
"personId":2356,
"activeBoolean":1
},
{
"personId":123617783,
"activeBoolean":1
}
],
"_links":{
"self":{
"href":"http://localhost:8080/api/users/1"
}
}
}
]
}}
Моя базовая сущность такова:
@Entity
public class User {
...
@Getter @Setter
private String userName;
@Getter @Setter
@OneToMany(mappedBy = "user")
private Set<Userperson> userPersons;
}
И один репозиторий:
@RepositoryRestResource
public interface UserRepo extends JpaRepository<User, Integer> {
}
Мое решение таково:
Просто НЕ выставляя Userperson @RepositoryRestResource, Spring Data Rest встроит вашу ассоциацию.
Если вы определяете @RepositoryRestResource для вложенного типа, Spring Data Rest будет отображать ссылку на ресурс, а не встраивать его.
Если вам нужен репозиторий вложенных типов для внутренней бизнес-логики, установите для него значение @RepositoryRestResource(exported = false), чтобы иметь такое же поведение.
Чтобы избежать проблемы 1+N, вы можете настроить ассоциацию для активной загрузки, возможно, используя @EntityGraph, как этот парень - хотя я еще не нашел лучший способ реализовать это в Spring Data Rest.