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