Выборочное расширение ассоциаций в ответе 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.

Другие вопросы по тегам