Выборочно расширять ассоциации в Spring Отклике Data Rest
У меня есть стандартная настройка данных JPA и Spring данных Spring, которая корректно возвращает ассоциации как ссылки на правильные ресурсы.
{
"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"
}
}
}
Однако в некоторых запросах мне хотелось бы, чтобы ассоциация с расширением "otherDomain" расширялась (поэтому клиенту не нужно выполнять N + 1 запросов для получения полных данных).
Можно ли настроить Spring Data Rest для обработки ответа таким образом?
Ответы
Ответ 1
Ответы по умолчанию должны оставаться неизменными, чтобы удостовериться, что полезная нагрузка для запросов PUT
симметрична тем, которые были возвращены GET
. Однако Spring Data REST вводит функцию, называемую проекциями (подробнее см. JIRA ticket), которая работает следующим образом:
Вы создаете выделенный интерфейс и добавляете все свойства, которые хотите включить в ответ:
public interface MyProjection {
String getMyProperty();
MyRelatedObject getOtherDomain();
}
Вы можете либо
- аннотировать интерфейс с помощью
@Projection
и поместить его в тот же пакет, что и тип домена или его подпапка
- или вручную зарегистрируйте проекцию с помощью
RepositoryRestConfiguration
и вызовите projectionConfiguration().addProjection(…)
вручную (путем расширения RepositoryRestMvcConfiguration
и переопределения configureRepositoryRestConfiguration(…)
).
Это приведет к тому, что ресурсы, доступные для типа домена, будут принимать параметр projection
(имя также настраивается ProjectionConfiguration
) с именем проекции. Если дано, мы пропустим рендеринг по умолчанию (который включает в себя рендеринг ссылок на связанные объекты, а не встраивание их), и пусть Джексон предоставит прокси-сервер, поддерживающий данный интерфейс.
Пример этого также можно найти в проекте Spring RESTBucks. См. OrderProjection
для определения интерфейса.
Ответ 2
Мое решение применимо ко всем запросам, но некоторые из них могут оказаться релевантными.
У меня есть симулятивная ситуация, где у меня есть ассоциация userPersons, вложенная в мой User ответ json, например:
{
"_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.