web-dev-qa-db-ja.com

Spring Data REST埋め込みリソースをインラインで追加する方法

Spring Data RESTとHateoasをHALブラウザーと組み合わせて使用​​しています。これは完全に機能しますが、特定のエンティティ(のセット)を関連付けたJSONダンプを作成したいと思います。オブジェクト。@Projectionを使用しましたが、再びスタックしました。

参考:通常の動作(埋め込みとリンクなど)は、新しいエンドポイント(埋め込みとリンクなし)以外にとどまる必要があります。

私の問題/質問をさらに説明するために:

class Person {
  String name;
  List<Company> companies;
}

class Company {
  String name;
  Address address;
}

class Address {
  String street;
}

今、私はこのようなものを見たいと思います:

{
   "name": "John",
   "companies": [
        {
            "name": "Stackoverflow",
            "address": {"street": "Highway blvd."}
        },
        {
            "name": "Oracle",
            "address": {"street": "Main rd."}
        }
   ]
}

私がこれを取得している間:

{
   "name": "John",
   "_links": {
        "self": {"href": "http...."},
        "companies": {"href": "http ..."}
   },
}

参照: http://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts

私の例では、リスト(会社)と複数のレベル:person-> company-> addressという2つの問題を紹介しました。両方が機能する必要があります(おそらく5つのレベルで、そのうちのいくつかは「多くの」関係を持っています)。

10
codesmith

あなたが特定したように、エンティティをインライン化するために受け入れられている方法は射影です。射影は常にインライン化されるため、1つのオプションは、エンティティごとに射影を作成し、次のように組み合わせる方法です。

_@Projection(name = "personProjection", types = Person.class)
public interface PersonProjection {

    String getFirstName();
    List<CompanyProjection> getCompanies();

}

@Projection(name = "companyProjection", types = Company.class)
public interface CompanyProjection {

    String getName();
    AddressProjection getAddress();

}

@Projection(name = "addressProjection", types = Address.class)
public interface AddressProjection {

    String getStreet();

}
_

_GET people/1?projection=personProjection_は引き続き__links_要素をレンダリングしますが、必要なネストを取得します。

_{
  "companies" : [ {
    "address" : {
      "street" : "123 Fake st",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/addresses/1{?projection}",
          "templated" : true
        }
      }
    },
    "name" : "ACME inc.",
    "_links" : {
      "self" : {
        "href" : "http://localhost:8080/companies/1{?projection}",
        "templated" : true
      },
      "address" : {
        "href" : "http://localhost:8080/companies/1/address"
      }
    }
  } ],
  "firstName" : "Will",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/1"
    },
    "person" : {
      "href" : "http://localhost:8080/people/1{?projection}",
      "templated" : true
    },
    "companies" : {
      "href" : "http://localhost:8080/people/1/companies"
    }
  }
}
_

または、CompanyエンティティとAddressエンティティを残りのリソースとして公開する必要がない場合は、リポジトリを@RepositoryRestResource(exported=false)でマークすると、どこにでもインライン化されます。投影を必要とせずに参照されます。

ただし、最後の注意点として、このリクエストはSpring Data RESTとSpringHATEOASの精神に反しており、n +1の問題を抱えている大きくて扱いにくいクエリを招いています。 Spring Data RESTは、ドメインモデルをAPIに変換するためのターンキーソリューションではなく、ディープオブジェクトグラフのレンダリング(それが意図されている場合)は、カスタムコントローラーエンドポイントとして公開する可能性があることを忘れないでください。条件を徹底的に制御できるアドホックベース。

15
Will Faithfull

2番目のエンドポイントでは、リンクが必要ない場合は、コントローラーとリソースが必要です。ここで、データをリソースにマップし、コントローラーからリソースのコレクションを返します。

0
Fahad Fazil