Spring Data Restにおけるエンティティ間の関連付け方法

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点です。

  1. Request bodyを「text/uri-list」にする
  2. 値を「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点です。

  1. Request bodyを「text/uri-list」にする
  2. 値を「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/

stackoverflow:How to maintain bi-directional relationships with Spring Data REST and JPA?

https://stackoverflow.com/questions/30464782/how-to-maintain-bi-directional-relationships-with-spring-data-rest-and-jpa

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です