(第2回) H2の接続設定、エンティティクラスの作成、data.sqlで初期データ作成【Spring Boot2】

H2入門の第2回です。H2データベースの接続設定(application.properties)、Spring Data JPAのエンティティクラスの作成、またDBの初期データの作成をやっていきます。Spring Bootの初心者・入門者の方は、参考にしてみてください。

動作環境と今回の目的

最終更新日:2022/11/27

前回は、H2データベースを試すためのSpring Bootのプロジェクト作成までをやりました。
(第1回) 手軽に試せるH2データベース入門【H2, Spring Boot2】

今回は、H2の接続設定やJavaのエンティティクラスの作成、またDBの初期データの作成をやっていきます。

・動作環境やバージョンは以下の通りです。
OS:macOS Big Sur(バージョン11.7.1)
開発環境:Eclipse(Pleiades All in One、4.16(2020-06)、Java Full Edition版)
Spring Boot:バージョン2.7.6
Java:11

今回作成するファイル

前回test-h2というSpring Bootのプロジェクトを作成しましたが、今回作成するファイルを先に書いておきます。
Spring Bootアプリ、H2の接続設定

作成するファイルは3つです。

  • Diary.java:Spring Data JPAのエンティティクラス
  • application.properties:H2の接続設定。このファイルはプロジェクト作成時に空の状態で作成されているはず。
  • data.sql:DML(Data Manipulation Language)ファイル

H2の接続設定、application.properties

まずは、application.propertiesファイルでH2接続設定をします。application.propertiesファイルは、Spring Bootプロジェクト作成時に以下のパスに自動で作られます。

src/main/resource/application.properties

application.propertiesファイルを編集します。ユーザ名とパスワードはコメントアウトしているので、設定しているのは"spring.datasource.driver-class-name"、"spring.datasource.url"プロパティの2箇所です。

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:hogedb
#とりあえず自分でテスト的にH2を試すだけなので、DBのユーザ名とパスワードはコメントアウトして未設定にしておく
#spring.datasource.username=hogeuser
#spring.datasource.password=pass

  • spring.datasource.driver-class-name:JDBCドライバーの完全修飾名。ここではH2へ接続するため"org.h2.Driver"にしています。
  • spring.datasource.url:データベースの接続URL。上の設定では、"jdbc:h2"がH2へ接続、"mem"がDBをインメモリ上に構築、"hogedb"がDB名です。

"spring.datasource.driver-class-name"プロパティは、"spring.datasource.driverClassName"でも良いです。

spring.datasource.driverClassName=org.h2.Driver

◾️H2のデータをファイル保存にしてデータを永続化する

H2のデータの保存先はメモリだけでなく、ファイルに保存する事もできます。ファイル保存だとデータを永続的に残せるので、アプリを終了してもデータは残ります。

H2をファイルベースで利用する時の方法や設定については別ページ(第8回)で説明していますので、そちらを参考にしてください。
(第8回)H2のデータをファイルに保存、データの永続化【Spring Boot2】

エンティティクラスの作成

次に、Spring Data JPAのエンティティクラスを作成します。今回は、日記、もしくはメモ帳やツイートなどのデータを想定して、単純なDiaryクラスを作成します。
src/main/java配下のcom.example.demoパッケージ下にDiary.javaファイルを作成して編集します。

package com.example.demo;

import java.time.LocalDateTime;

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

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
//@Table(name = "diaries")	//指定しないとテーブルはクラス名と同じdiary
public class Diary {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private String comment;
    @Column(name = "create_datetime", nullable = false)
    private LocalDateTime createDatetime;
}

エンティティクラスのフィールドは3つだけです。

  • id:主キー
  • comment:日記の本体コメント
  • createDatetime:投稿日時

まず、Spring Data JPAのエンティティクラスである事を表すために、クラス名に@Entityを付けます。

@Tableはコメントアウトしていますが、エンティティクラス名とH2データベースのテーブル名が異なる場合、@Tableのnameでテーブル名を指定して、エンティティクラスとテーブル名をマッピングします。
上のコードでは@Tableは指定していませんので、アプリ起動時にエンティティクラスと同じ名前のDiaryというテーブルが、Spring Data JPAによって自動生成されます。

フィールドのidに付与している@Idは、エンティティの主キーという事です。
@GeneratedValueは主キーが自動採番される事、strategy=GenerationType.IDENTITYは採番方法を示しています。

フィールドのcreateDatetimeに付与している@Columnは、テーブルのフィールドに対する設定をしています。「name = "create_datetime"」はテーブルにあるフィールド名を"create_datetime"に設定し、「nullable = false」はフィールドの値をnull禁止(not null)にしています。
@Columnを付与しないと、エンティティのフィールド名とテーブルのフィールド名は同じになります。

@Data、@NoArgsConstructor、@AllArgsConstructorは全て、Lombokのアノテーションです。これらを付ける事で、フィールドのセッター・ゲッター、クラスのコンストラクタのコードが自動生成されるので、エンティティクラスのコード量を削減できます。

Eclipseの場合、アウトラインビューでクラスにあるフィールド、メソッド、コンストラクタの一覧が見れますので、ここでLombokによって自動生成されたメソッドなども確認できます。

data.sqlの作成、DBの初期データの作成

次に、初期データを作成するためのDML(Data Manipulation Language)ファイルの作成です。
Spring Bootでは、プロジェクトのsrc/main/resourcesディレクトリ下にdata.sqlファイルを作成し、このファイルにDMLのInsert SQLを書いておくと、Spring Bootアプリ起動時に自動でdata.sqlをロードしてSQLを実行して初期データを作ってくれます。

実際にdata.sqlファイルを作成して編集します。
(*data.sqlに書くsqlをコメントアウトしたい場合は、行頭に"--"を付けます)

INSERT INTO diary(comment, create_datetime) VALUES('今日は晴れ。コメント1', LOCALTIME());
INSERT INTO diary(comment, create_datetime) VALUES('comment 2', LOCALTIME());
INSERT INTO diary(comment, create_datetime) VALUES('こめんと3', LOCALTIME());
上で作成したエンティティクラスのDiaryに合わせてsqlを作成しました。テスト的に3レコード分追加するsqlです。
LOCALTIME()は現在日時を生成します。

また、application.propertiesファイルにspring.jpa.defer-datasource-initializationプロパティの設定を1行追加します。

spring.jpa.defer-datasource-initialization=true

spring.jpa.defer-datasource-initializationプロパティは、Spring Bootのバージョン2.5以上に必要な設定なので、バージョン2.4以下なら書く必要は無いです。

これは、Spring Bootの2.4から2.5へのバージョンアップ時にdata.sqlとschema.sql周りのデータ初期化スクリプトの仕様変更があり、2.4系まではエンティティクラスがある場合、エンティティクラスからDBのテーブルが生成された後に、data.sqlにあるInsert SQLが実行される流れだったのが、2.5系にバージョンアップされてからはその順序が逆になり、先にdata.sqlがロードされてにSQLが実行され、その後にエンティティクラスからDBのテーブルが生成されるようになりました。

ですので、バージョン2.5以上ではDBテーブルが無い状態でdata.sqlにあるInsert SQLが実行されてエラーが発生するのですが、上記の「spring.jpa.defer-datasource-initialization=true」を追記すれば、順序をエンティティクラスがテーブルを生成して、その後にdata.sqlを実行する事ができます。

この問題については別ページでもう少し詳しく説明しているので、よければ参考にしてください。
Spring Boot2.4から2.7へバージョンアップ時にエラー発生

◾️DDL(Data Definition Language)のschema.sql
Spring Bootでは、DMLのdata.sqlだけでなく、DDLのschema.sqlファイルをsrc/main/resourcesディレクトリ下に作成すれば、アプリ起動時にdata.sqlと同じく自動でschema.sqlをロードして実行してくれます。

そうすれば、schema.sqlでDBのテーブルを作成して、data.sqlでDBデータを初期化できるので、Diaryエンティティクラスでテーブル生成する必要がなくなりますし、この方法であれば、Spring Bootのバージョン2.5以上でも"spring.jpa.defer-datasource-initialization"プロパティを設定する必要がありません。

schema.sqlを使う方法は第7回の記事で説明しているので、よければそちらを参考にしてください。
(第7回) schema.sqlを使用してDBのテーブル作成【H2, Spring Boot2】

Spring Boot 本をAmazonで探す [広告]

最後に、次回

以上今回は、H2への接続設定、エンティティクラスDiaryの作成、DMLのdata.sqlを作成しました。

これでアプリを実行すれば、H2のDBがインメモリで生成され、エンティティクラスDiaryからSpring Data JPAによってdiaryテーブルが自動生成され、data.sqlで書いた3レコード分のデータが生成されます。

次回は、Spring Bootアプリの起動によって生成されるH2DBのテーブルやデータは、H2の管理ツールの"H2 Console"で確認する事ができますので、H2 Consoleの使い方について書いていきます。

(第3回) H2のブラウザ管理ツール"H2 Console"の使い方【H2, Spring Boot2】
H2データベース入門【Spring Boot】トップに戻る

Kindle Unlimitedなら対象の本が定額で読み放題 [広告]
対象本には、プログラミングなどのIT関連本、マンガ、雑誌、ビジネス書などがたくさんあります!

Spring Bootの記事

Spring Boot2で日記投稿ウェブアプリ開発入門トップページ
Spring Bootでシンプルな日記投稿ウェブアプリの開発しながら、入門者・初心者にもわかりやすいように説明しています。DBを使用して、新規投稿、編集、削除、一覧表示という基本的なCRUD機能を備えたアプリです。