Spring Data Restにおけるエンティティ間の関連付け方法についてご紹介します。
目次
条件
- Spring Tool Suite 4
- Spring Boot 2.5.0
- h2
- gradle
前提
以下のようなデータを考えます。
投稿 : コメント = 1 : N
一つの投稿について、複数のコメントが付けられるものとします。
プロジェクト依存関係
以下を使用します。
- Spring Data JPA
- H2 Database
- Rest Repositories
- Lombok
パッケージ構成
一方向の@ManyToOneのエンティティの関連付け
モデル
Post.java
package com.example.demo.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import lombok.Data; @Data @Entity public class Post { @Id @GeneratedValue private Long id; @Column private String title; }
Comment.java
package com.example.demo.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; import lombok.Data; @Data @Entity public class Comment { @Id @GeneratedValue private Long id; @Column private String message; @ManyToOne private Post post; }
リポジトリ
PostRepository.java
package com.example.demo.repository; import org.springframework.data.repository.CrudRepository; import com.example.demo.model.Post; public interface PostRepository extends CrudRepository<Post, Long>{ }
CommentRepository.java
package com.example.demo.repository; import org.springframework.data.repository.CrudRepository; import com.example.demo.model.Comment; public interface CommentRepository extends CrudRepository<Comment, Long>{ }
データ登録
PostとComment間の関連付けを行うためには、PostおよびCommentのデータが登録済みである必要があります。
Swaggerの画面で、関連付けデータの登録を行います。
ポイントは以下の2点です。
- Request bodyを「text/uri-list」にする
- 値を「http://localhost:8080/posts/1」とする
対象コメントが「記事1」に紐づいたため、以下のGETリクエストでデータが取得できることがわかります。
http://localhost:8080/comments/2/post
一方向の@OneToManyのエンティティの関連付け
今度は先ほどとは逆の関連付けを考えます。
PostはCommentのリストを持っているが、CommentはPostへの紐づけがわからない状態です。
モデル
Post.java
package com.example.demo.model; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import lombok.Data; @Data @Entity public class Post { @Id @GeneratedValue private Long id; @Column private String title; @OneToMany(cascade=CascadeType.ALL) private List<Comment> comments; }
Comment.java
package com.example.demo.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import lombok.Data; @Data @Entity public class Comment { @Id @GeneratedValue private Long id; @Column private String message; }
データ登録
先ほどと同様、Swaggerの画面で、関連付けデータの登録を行います。
ポイントは以下の2点です。
- Request bodyを「text/uri-list」にする
- 値を「http://localhost:8080/comments/2」のように複数指定する
対象記事に指定したコメント紐づいたため、以下のGETリクエストでデータが取得できることがわかります。
http://localhost:8080/posts/1/comments
注意事項
PUTリクエストで関連付けデータ登録を行うと、一旦全ての関連付けデータが削除され、新たに指定したものが登録されます。
双方向の@OneToMany/@ManyToOneのエンティティの関連付け
結論から言うと、うまく動作しません。
Commentから見た関連付けは、前述の通りの動作となります。
しかし、Postからの関連付けは登録できません。
詳細は、下記の参考記事をご確認ください。
・双方向の関連付けは行わず、一方向の関連付けのみ行いユースケース毎に明示的なリポジトリを呼ぶことを推奨しています。
参考
Handling Associations Between Entities with Spring Data REST
https://reflectoring.io/relations-with-spring-data-rest/