15
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【初心者向け】Spring JPA の Entity 作成のサンプル

Last updated at Posted at 2021-08-09

はじめに

とりあえず Spring JPA を触って動かすだけのサンプルです。
JPA を使用して、一対多、多対多の Entity(テーブル)を作成します。

サンプルを作成する環境は、Windows ですが、Mac でも何ら変わりません。
DBMS は MySQL を使用します。

<参考サイト>
デフォルトマッピング(双方向のリレーションシップ)

1. サンプル作成の前準備

1-1. データベースの用意

コマンドプロンプトから MySQL を開いて「spring_jpa」というデータベースを作成します(データベース名は何でも構いません)。

データベースの作成
mysql> create database spring_jpa;
Query OK, 1 row affected (0.25 sec)

次に、アクセス用のユーザーを作成します。
以下は、ユーザー名「yama3」、パスワード「123456」とする場合の例です。

ユーザーの作成
mysql> create user 'yama3'@'localhost' identified by '123456';
Query OK, 0 rows affected (1.41 sec)

作成したユーザーにデータベース(spring_jpa)に対する全ての権限を与えておきます。

ユーザーの権限を設定
mysql> grant all on spring_jpa.* to 'yama3'@'localhost';
Query OK, 0 rows affected (0.32 sec)

MySQL のインストールや操作方法などの詳しいことは、こちらのサイトを参照してください。

1-2. プロジェクトの作成

サンプル用に、プロジェクトを作成します。
名前(Name)は適当に「JpaSample」としておきました。
ビルドツールは「Maven」、Java バージョンは「11」ですが、このあたりも適当で大丈夫です。
2021-08-09 101310.png
ライブラリは、「Spring Data JPA」、「Spring Web」、「Thymeleaf」、「MySQL Driver」を選択しておきます。
2021-08-09 110238.png

2. 最低限のサンプル

最初に、エンティティ(≒ テーブル)を1つ作るだけの簡素なサンプルです。
application.properties(既にあるファイル)には、データベース接続などに必要な事項を記載します。
User.java(新ファイル作成)には、エンティティの定義を記述します。
2021-08-09 113646.png

2-1. application.properties のコード

データベース名(spring_jpa)、username(yama3)、passwprd(123456)は、手元の環境に合わせて記載してください。
あとは、そのままで大丈夫です。

/src/main/resources/application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/spring_jpa
spring.datasource.username=yama3
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update

spring.thymeleaf.cache=false

<参考>
MyISAMの代わりにMysql InnoDBテーブルを作成する

2-2. User.java のコード

設定するカラム(フィールド変数)は、id、name の2つだけです。

/src/main/java/com/example/demo/User.java
package com.example.demo;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @Column(name = "user_name", nullable = false, length = 50)
    private String userName;
    
    // 空のコンストラクタ
    public User() {}
    
    // Getter、Setter
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

2-2-1. アノテーション

使用しているアノテーションは次のとおりです。

アノテーション 内容
@Entity Entity クラスであることを示す
@Id 主キーであることを示す(Unique、Not Null も付与)
@GeneratedValue 値を自動生成する(= Auto Increment)
@Column カラムの設定を記述(カラム名、Not Null、サイズ など)

@GeneratedValue の GenerationType には、AUTO、IDENTITY などがありますが、IDENTITY を使用しておくのが無難です。

@Columnの指定内容

項目 内容
name データベースでのカラム名を指定(無ければ変数名から生成)
nullable Null を許可するか否かの指定
length データのサイズを指定

name を書かなければ、フィールド変数名がそのままデータベースのカラム名になります。
例えば、変数名が「userName」であれば、「user_name」とスネークケースに自動的に変換されます(つまり、上記サンプルコードでは、name の指定をしなくとも同じ結果になります)。

2-2-2. コンストラクタ、Getter、Setter

JPA には原則として空のコンストラクタが必要になるので作成しておきます(参考記事)。なお、このサンプルではコンストラクタがなくとも動きます。

GetterSetter も必要となるので、STS の自動生成などを使用して作成しておきます。

2-3. プロジェクトの実行

プロジェクトを実行します。
2021-08-09 122604.png
コンソールの赤枠のところで、CREATE TABLE 文が実行されて、作成した User エンティティ の内容に沿ったテーブルが自動で作成されます。

コマンドプロンプトから作成されたテーブルを確認すると次のようになっています。

コマンドプロンプト
mysql> show create table user\G
*************************** 1. row ***************************
       Table: user
Create Table: CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.06 sec)

3. 一対多のサンプル

2021-08-09 140123.png
上記のように、usermessage が、一対多の関係となる形でエンティティを作成します。
message エンティティの user_id が外部キーとなり、user エンティティの主キーである id と紐付くことになります。

これは、ユーザーが複数のメッセージを投稿できるというような場合の関係になります。

3-1. Message.java のコード

Message.java というクラスファイルを作って次のように Message エンティティを作成します。

/src/main/java/com/example/demo/Message.java
package com.example.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Message {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer messageId;
    
    private String comment;
    
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    public Message() {}

    public Integer getMessageId() {
        return messageId;
    }
    public void setMessageId(Integer messageId) {
        this.messageId = messageId;
    }
    public String getComment() {
        return comment;
    }
    public void setComment(String comment) {
        this.comment = comment;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}

3-2. User.java のコード

User エンティティは、次のように作成(修正)します。

/src/main/java/com/example/demo/User.java
package com.example.demo;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @Column(name = "user_name", nullable = false, length = 50)
    private String userName;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Message> messages;
    
    public User() {}
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public List<Message> getMessages() {
        return messages;
    }
    public void setMessages(List<Message> messages) {
        this.messages = messages;
    }
}

3-3. 簡単な説明

3-3-1. @ManyToOne

Message エンティティは、1つの User エンティティと結びつくため、@ManyToOne アノテーションを使用します。
フィールド変数として User クラスを単数で指定します。

Messageエンティティ
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

@JoinColumn では、name = "user_id" と指定しています。
これは、データベース上のカラム名として反映されます。

3-3-2. @OneToMany

User エンティティは、複数の Message エンティティと結びつくため、@OneToMany アノテーションを使用します。
フィールド変数として Message クラスをList型(複数)で指定します。

Userエンティティ
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Message> messages;

mappedBy = "user" で指定している user は、Message から参照する際に使用されます。
例えば、Spring 式言語(SpEL)では、message.user.user_id という形で記述されます。

3-4. プロジェクトの実行

プロジェクトを実行します。

2021-08-09 143741.png

作成されたテーブルを確認します。

コマンドプロンプト
mysql> show create table message\G
*************************** 1. row ***************************
       Table: message
Create Table: CREATE TABLE `message` (
  `message_id` int NOT NULL AUTO_INCREMENT,
  `comment` varchar(255) DEFAULT NULL,
  `user_id` int DEFAULT NULL,
  PRIMARY KEY (`message_id`),
  KEY `FKb3y6etti1cfougkdr0qiiemgv` (`user_id`),
  CONSTRAINT `FKb3y6etti1cfougkdr0qiiemgv` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.03 sec)

次のところで、外部キーが設定されていることが確認できます。

抜粋
FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)

4. 多対多のサンプル

2021-08-09 145536.png
上記のように、usermessage が、多対多となる関係も追加します。
多対多の関係を持たせるために、user エンティティの主キーと、message エンティティの主キーの2つを外部キーとして持つ結合テーブル(message_user)を作成します。

このような関係は、ユーザーがメッセージに対して「いいね」ボタンを押す機能を実装するような場合に使用できます。

  • user は複数のメッセージに対して「いいね」ボタンを押すことができる
  • message は複数のユーザーから「いいね」ボタンを押されることができる

なお、結合テーブルの Entity は作成しませんが、データベースのテーブルは作成されます。

4-1. Message.java のコード

Message エンティティは、次のように作成(修正)します。

/src/main/java/com/example/demo/Message.java
package com.example.demo;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;

@Entity
public class Message {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer messageId;
    
    private String comment;
    
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToMany
    @JoinTable(name="message_user", joinColumns = @JoinColumn( name = "message_id"),
            inverseJoinColumns = @JoinColumn(name="user_id"))
    private List<User> userList;

    public Message() {}

    public Integer getMessageId() {
        return messageId;
    }
    public void setMessageId(Integer messageId) {
        this.messageId = messageId;
    }
    public String getComment() {
        return comment;
    }
    public void setComment(String comment) {
        this.comment = comment;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public List<User> getUserList() {
        return userList;
    }
    public void setUserList(List<User> userList) {
        this.userList = userList;
    }
}

4-2. User.java のコード

User エンティティは、次のように作成(修正)します。

/src/main/java/com/example/demo/User.java
package com.example.demo;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @Column(name = "user_name", nullable = false, length = 50)
    private String userName;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Message> messages;
    
    @ManyToMany( mappedBy = "userList")
    private List<Message> messagelist;    

    public User() {}
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public List<Message> getMessages() {
        return messages;
    }
    public void setMessages(List<Message> messages) {
        this.messages = messages;
    }
    public List<Message> getMessagelist() {
        return messagelist;
    }
    public void setMessagelist(List<Message> messagelist) {
        this.messagelist = messagelist;
    }
}

4-3. 簡単な説明

4-3-1. @ManyToMany

複数の Message エンティティが、複数の User エンティティと結びつくため、@ManyToMany アノテーションを使用します。

この多対多の関係の所有者を Message エンティティとみなして、 Message エンティティ側に、結合テーブルの定義を記載しています。

Messageエンティティ
    @ManyToMany
    @JoinTable(name="message_user", joinColumns = @JoinColumn( name = "message_id"),
            inverseJoinColumns = @JoinColumn(name="user_id"))
    private List<User> userList;
Userエンティティ
    @ManyToMany( mappedBy = "userList")
    private List<Message> messagelist;    

結合テーブルは、所有者側のエンティティで @JoinTable を使用して定義します。

項目 内容
name 結合テーブルの名前を指定
joinColumns 所有者エンティティへの外部キーのカラム名を指定
inverseJoinColumns 非所有者エンティティへの外部キーのカラム名を指定

mappedBy = "userList" で指定している userList は、Message から参照する際に使用されます。

4-4. プロジェクトの実行

プロジェクトを実行します。
2021-08-09 153137.png
作成されたテーブルを確認します。

コマンドプロンプト
mysql> show create table message_user\G
*************************** 1. row ***************************
       Table: message_user
Create Table: CREATE TABLE `message_user` (
  `message_id` int NOT NULL,
  `user_id` int NOT NULL,
  KEY `FKkqjauebfx5xkymdbpv26seckx` (`user_id`),
  KEY `FKfh34sth5igv111to5girgymqu` (`message_id`),
  CONSTRAINT `FKfh34sth5igv111to5girgymqu` FOREIGN KEY (`message_id`) REFERENCES `message` (`message_id`),
  CONSTRAINT `FKkqjauebfx5xkymdbpv26seckx` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

意図した形で、message_user テーブル(結合テーブル)が作成されていることが確認できます。

<参考サイト>
デフォルトマッピング(双方向のリレーションシップ)
@JoinTable

15
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?