Spring Data RESTの予測と抜粋
1. 概要
この記事では、Spring DataRESTのプロジェクションと抜粋の概念について説明します。
use projections to create custom views of our models and how to use excerpts as default views to resource collectionsの方法を学びます。
2. 私たちのドメインモデル
まず、ドメインモデルを定義することから始めましょう:BookとAuthor.
Bookのエンティティクラスを見てみましょう。
@Entity
public class Book {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String title;
private String isbn;
@ManyToMany(mappedBy = "books", fetch = FetchType.EAGER)
private List authors;
}
そして、Authorモデル:
@Entity
public class Author {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "book_author",
joinColumns = @JoinColumn(
name = "book_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(
name = "author_id", referencedColumnName = "id"))
private List books;
}
また、2つのエンティティには多対多の関係があります。
次に、モデルごとに標準のSpring DataRESTリポジトリを定義しましょう。
public interface BookRepository extends CrudRepository {}
public interface AuthorRepository extends CrudRepository {}
これで、Bookエンドポイントにアクセスして、http://localhost:8080/books/{id}:のIDを使用して特定のBook’sの詳細を取得できます。
{
"title" : "Animal Farm",
"isbn" : "978-1943138425",
"_links" : {
"self" : {
"href" : "http://localhost:8080/books/1"
},
"book" : {
"href" : "http://localhost:8080/books/1"
},
"authors" : {
"href" : "http://localhost:8080/books/1/authors"
}
}
}
Authorモデルにはリポジトリがあるため、作成者の詳細は応答の一部ではないことに注意してください。 ただし、それらへのリンクは見つかります–http://localhost:8080/books/1/authors.
3. 投影の作成
時々、we’re only interested in a subset or a custom view of an entity’s attributes。 そのような場合、投影法を利用できます。
Spring Data RESTプロジェクションを使用して、Bookのカスタムビューを作成しましょう。
まず、CustomBookと呼ばれる単純なProjectionを作成します。
@Projection(
name = "customBook",
types = { Book.class })
public interface CustomBook {
String getTitle();
}
our projection is defined as an interface with an @Projection annotationに注意してください。 name属性を使用してプロジェクションの名前をカスタマイズしたり、types属性を使用して適用するオブジェクトを定義したりできます。
この例では、CustomBookプロジェクションには本のtitleのみが含まれます。
Projection:を作成した後、Bookの表現をもう一度見てみましょう。
{
"title" : "Animal Farm",
"isbn" : "978-1943138425",
"_links" : {
"self" : {
"href" : "http://localhost:8080/books/1"
},
"book" : {
"href" : "http://localhost:8080/books/1{?projection}",
"templated" : true
},
"authors" : {
"href" : "http://localhost:8080/books/1/authors"
}
}
}
素晴らしい、投影へのリンクを見ることができます。 http://localhost:8080/books/1?projection=customBookで作成したビューを確認しましょう。
{
"title" : "Animal Farm",
"_links" : {
"self" : {
"href" : "http://localhost:8080/books/1"
},
"book" : {
"href" : "http://localhost:8080/books/1{?projection}",
"templated" : true
},
"authors" : {
"href" : "http://localhost:8080/books/1/authors"
}
}
}
ここでは、titleフィールドのみを取得し、isbnはカスタムビューに存在しなくなっていることがわかります。
原則として、http://localhost:8080/books/1?projection=\{projection name}.で投影法の結果にアクセスできます
また、モデルと同じパッケージでProjectionを定義する必要があることに注意してください。 または、RepositoryRestConfigurerAdapterを使用して明示的に追加することもできます。
@Configuration
public class RestConfig extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(
RepositoryRestConfiguration repositoryRestConfiguration) {
repositoryRestConfiguration.getProjectionConfiguration()
.addProjection(CustomBook.class);
}
}
4. 射影への新しいデータの追加
それでは、新しいデータをプロジェクションに追加する方法を見てみましょう。
前のセクションで説明したように、投影を使用して、ビューに含める属性を選択できます。 さらに、元のビューに含まれていないデータを追加することもできます。
4.1. 隠しデータ
デフォルトでは、IDは元のリソースビューに含まれていません。
結果にIDを表示するには、idフィールドを明示的に含めることができます。
@Projection(
name = "customBook",
types = { Book.class })
public interface CustomBook {
@Value("#{target.id}")
long getId();
String getTitle();
}
これで、http://localhost:8080/books/1?projection=\{projection name} での出力は次のようになります。
{
"id" : 1,
"title" : "Animal Farm",
"_links" : {
...
}
}
元のビューから非表示にされたデータを@JsonIgnore.で含めることもできることに注意してください
4.2. 計算データ
リソース属性から計算された新しいデータを含めることもできます。
たとえば、著者数をProjectionに含めることができます。
@Projection(name = "customBook", types = { Book.class })
public interface CustomBook {
@Value("#{target.id}")
long getId();
String getTitle();
@Value("#{target.getAuthors().size()}")
int getAuthorCount();
}
{
"id" : 1,
"title" : "Animal Farm",
"authorCount" : 1,
"_links" : {
...
}
}
4.3. 関連リソースへの簡単なアクセス
最後に、通常、関連するリソースにアクセスする必要がある場合(この例では本の著者のように)、明示的に含めることで余分なリクエストを回避できます。
@Projection(
name = "customBook",
types = { Book.class })
public interface CustomBook {
@Value("#{target.id}")
long getId();
String getTitle();
List getAuthors();
@Value("#{target.getAuthors().size()}")
int getAuthorCount();
}
そして、最終的なProjection出力は次のようになります。
{
"id" : 1,
"title" : "Animal Farm",
"authors" : [ {
"name" : "George Orwell"
} ],
"authorCount" : 1,
"_links" : {
"self" : {
"href" : "http://localhost:8080/books/1"
},
"book" : {
"href" : "http://localhost:8080/books/1{?projection}",
"templated" : true
},
"authors" : {
"href" : "http://localhost:8080/books/1/authors"
}
}
}
次に、抜粋を見ていきます。
5. 抜粋
抜粋は、リソースコレクションのデフォルトビューとして適用される予測です。
BookRepositoryをカスタマイズして、コレクションの応答にcustomBookProjectionを自動的に使用してみましょう。
これを実現するために、@RepositoryRestResourceアノテーションのexcerptProjection属性を使用します。
@RepositoryRestResource(excerptProjection = CustomBook.class)
public interface BookRepository extends CrudRepository {}
これで、http://localhost:8080/booksを呼び出すことで、customBookが書籍コレクションのデフォルトビューであることを確認できます。
{
"_embedded" : {
"books" : [ {
"id" : 1,
"title" : "Animal Farm",
"authors" : [ {
"name" : "George Orwell"
} ],
"authorCount" : 1,
"_links" : {
"self" : {
"href" : "http://localhost:8080/books/1"
},
"book" : {
"href" : "http://localhost:8080/books/1{?projection}",
"templated" : true
},
"authors" : {
"href" : "http://localhost:8080/books/1/authors"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/books"
},
"profile" : {
"href" : "http://localhost:8080/profile/books"
}
}
}
同じことが、http://localhost:8080/authors/1/booksで特定の著者による本を表示する場合にも当てはまります。
{
"_embedded" : {
"books" : [ {
"id" : 1,
"authors" : [ {
"name" : "George Orwell"
} ],
"authorCount" : 1,
"title" : "Animal Farm",
"_links" : {
"self" : {
"href" : "http://localhost:8080/books/1"
},
"book" : {
"href" : "http://localhost:8080/books/1{?projection}",
"templated" : true
},
"authors" : {
"href" : "http://localhost:8080/books/1/authors"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/authors/1/books"
}
}
}
前述のように、抜粋はコレクションリソースにのみ自動的に適用されます。 単一のリソースの場合、前のセクションで示したように、projectionパラメータを使用する必要があります。
これは、投影を単一のリソースのデフォルトビューとして適用すると、部分ビューからリソースを更新する方法を知ることが難しくなるためです。
最後に、projections and excerpts are meant for the read-only purposeを覚えておくことが重要です。
6. 結論
Spring Data RESTプロジェクションを使用してモデルのカスタムビューを作成する方法を学びました。 また、リソースコレクションのデフォルトビューとして抜粋を使用する方法も学びました。
例の完全なソースコードはover on GitHubにあります。