背景・目的
Spring Bootでデータベースへのアクセスを試してみたでは、DBアクセスを試してみました。
今回は、Accessing JPA Data with RESTを試してみます。
まとめ
下記に特徴を整理します
特徴 | 説明 |
---|---|
H2 | ・Java SQL データベース ・高速、OSS、JDBC ・組み込み、サーバ、インメモリDB ・ブラウザベースのコンソール ・スモールフットプリント、2.5MBのJarファイル |
H2の主な特徴 | ・非常に高速なデータベースエンジン ・オープンソース ・Javaで書かれている ・標準SQL、JDBC APIをサポート ・組み込みおよびサーバーモード、クラスタリングのサポート ・強力なセキュリティ機能 ・PostgreSQL ODBCドライバ ・複数バージョンの同時実行 |
H2の接続モード | ・埋め込みモード(JDBC を使用したローカル接続) ・サーバー モード (TCP/IP 経由の JDBC または ODBC を使用したリモート接続) ・混合モード(ローカル接続とリモート接続を同時に実行) |
概要
今回、RESTによりリクエストを受けて、H2データベースにデータを保存します。
H2
H2 Database Engineを基に整理します。
Welcome to H2, the Java SQL database. The main features of H2 are:
- Very fast, open source, JDBC API
- Embedded and server modes; in-memory databases
- Browser based Console application
- Small footprint: around 2.5 MB jar file size
- Java SQL データベース
- 高速、OSS、JDBC
- 組み込み、サーバ、インメモリDB
- ブラウザベースのコンソール
- スモールフットプリント、2.5MBのJarファイル
Features
主な特徴
- 非常に高速なデータベースエンジン
- オープンソース
- Javaで書かれた
- 標準SQL、JDBC APIをサポート
- 組み込みおよびサーバーモード、クラスタリングのサポート
- 強力なセキュリティ機能
- PostgreSQL ODBCドライバ
- 複数バージョンの同時実行
追加機能
- ディスクベースまたはインメモリのデータベースとテーブル、読み取り専用データベースのサポート、一時テーブル
- トランザクション サポート (コミットされていない読み取り、コミットされた読み取り、繰り返し読み取り、スナップショット)、2 フェーズ コミット
- 複数の接続、行レベルのロック
- コストベースのオプティマイザー、複雑なクエリに遺伝的アルゴリズムを使用、管理不要
- スクロール可能で更新可能な結果セットのサポート、大きな結果セット、外部結果のソート、関数は結果セットを返すことができます
- 暗号化データベース(AES)、SHA-256パスワード暗号化、暗号化機能、SSL
SQL サポート
- 複数のスキーマ、情報スキーマのサポート
- 参照整合性 / カスケード制約、チェック制約による外部キー制約
- 内部結合と外部結合、サブクエリ、読み取り専用ビュー、インラインビュー
- トリガーと Java 関数 / ストアド プロシージャ
- XMLやロスレスデータ圧縮を含む多くの組み込み関数
- ラージオブジェクト(BLOB/CLOB)や配列を含む幅広いデータ型
- シーケンスと ID 列、生成された列 (関数ベースのインデックスに使用できます)
- ORDER BY、GROUP BY、HAVING、UNION、OFFSET / FETCH (PERCENT および WITH TIES を含む)、LIMIT、TOP、DISTINCT / DISTINCT ON (...)
- ウィンドウ関数
- ICU4Jライブラリのサポートを含む照合のサポート
- ユーザーとロールのサポート
- IBM DB2、Apache Derby、HSQLDB、MS SQL Server、MySQL、Oracle、PostgreSQL の互換モード。
セキュリティ機能
- SQLインジェクション問題に対する解決策が含まれています
- ユーザーパスワード認証にはSHA-256とソルトを使用します
- サーバー モード接続の場合、ユーザー パスワードはネットワーク経由でプレーン テキストで送信されることはありません (安全でない接続を使用している場合でも、これは TCP サーバーにのみ適用され、H2 コンソールには適用されません。また、データベース URL でパスワードを設定した場合にも適用されません)。
- すべてのデータベースファイル(データのバックアップに使用できるスクリプトファイルを含む)は、AES-128暗号化アルゴリズムを使用して暗号化できます
- リモートJDBCドライバはTLS経由のTCP/IP接続をサポートします。
- 内蔵ウェブサーバーはTLS経由の接続をサポートしています
- パスワードは文字列ではなく文字配列を使用してデータベースに送信できます。
その他の機能とツール
- フットプリントが小さい(約2.5 MB)、メモリ要件が低い
- 複数のインデックスタイプ(Bツリー、ツリー、ハッシュ)
- 多次元インデックスのサポート
- CSV(カンマ区切り値)ファイルのサポート
- リンクされたテーブルと組み込みの仮想「範囲」テーブルのサポート
- ステートメントをサポートEXPLAIN PLAN; 洗練されたトレースオプション
- パフォーマンスを向上させるために、データベースの終了を遅らせたり無効にしたりすることができます。
- オートコンプリート機能を備えた Web ベースのコンソール アプリケーション (多くの言語に翻訳)
- データベースはSQLスクリプトファイルを生成できる
- データベースの内容をダンプできるリカバリツールが含まれています
- 変数のサポート(たとえば、累計を計算するため)
- 準備されたステートメントの自動再コンパイル
- 少数のデータベースファイルを使用する
- データの整合性を保つために、各レコードとログエントリにチェックサムを使用します。
- 十分にテスト済み(高いコード カバレッジ、ランダム化されたストレス テスト)
接続モード
次の接続モードがサポートされています。
- 埋め込みモード(JDBC を使用したローカル接続)
- サーバー モード (TCP/IP 経由の JDBC または ODBC を使用したリモート接続)
- 混合モード(ローカル接続とリモート接続を同時に実行)
実践
前提
下記を前提としています。
- Mac
- VSCode
- Java 17
- Maven 3.9.8
プロジェクトの作成
- VSCodeを起動します
- 表示>コマンドパレットをクリックします
- 下記を選択します
- Spring Initializrを選択し、3.3.1
- Java
- GroupIdを指定します
- ArtifactIdを指定します
- Package TypeにJarを指定します
- Javaバージョンに17を指定します
- DependencyにSpring Webを指定します
- 作成後、Add Workspaceをクリックします
- 追加されました
pom.xmlの修正
- dependenciesに下記を追加します
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency>
application.properties
- H2 Databaseを利用するためにapplication.propertiesに下記を追加します。
spring.application.name=rest-db spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.h2.console.enabled=true
Create a Domain Object
- Personクラスを作成します
- 下記のコードを追加します
package com.example.data.rest_db; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; // Add this import statement import jakarta.persistence.Id; import jakarta.persistence.Table; @Entity @Table(name = "people") public class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column private Long id; @Column(length = 50,nullable = false) private String firstName; @Column(length = 50,nullable = false) private String lastName; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
-
@Entity
- JPAエンティティとして認識される
-
@Table(name="people")
- エンティティクラスに割り当てられるテーブルを指定する
- nameでテーブル名を指定(省略も可能)
-
@Id
- プライマリーキーになる
-
@Column
- フィールドに割り当てられるカラム名を指定する(省略した場合、フィールド名がそのままカラム名として使われる)
-
Create a Person Repository
- com.example.data.rest_db.repositoriesパッケージを作成します
- PersonRepositoryインタフェイスを作成します
- 下記のコードを追加します
package com.example.data.rest_db.repositories; import com.example.data.rest_db.Person; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface PersonRepository extends JpaRepository<Person, Long> { }
-
@Repository
- データアクセスを表している
-
Controllerを作成する
- WebControllerクラスを作成します
- 下記のコードを追加します
package com.example.data.rest_db; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import com.example.data.rest_db.repositories.PersonRepository; import jakarta.transaction.Transactional; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import java.util.List; // Add this import statement import org.springframework.web.bind.annotation.RequestMethod; @Controller public class WebController { @Autowired PersonRepository repository; @RequestMapping("/") public ModelAndView index( @ModelAttribute("formModel") Person person, ModelAndView mav) { mav.setViewName("index"); mav.addObject("title","Test page"); mav.addObject("message","This is JPA sample content."); List<Person> list = repository.findAll(); mav.addObject("people", list); return mav; } @RequestMapping(value = "/", method=RequestMethod.POST) @Transactional public ModelAndView form( @ModelAttribute("formModel") Person person, ModelAndView mav) { repository.saveAndFlush(person); return new ModelAndView("redirect:/"); } }
-
@Autowired
- PersonRepositoryインスタンスをフィールドに関連付ける
- Beanオブジェクトに関連付けを行う
-
findAllメソッド
- PersonRepositoryには、findAllのメソッドはない
- 継承元のJpaRepositoryに用意されている
-
@ModelAttribute
- エンティティクラスのインスタンスを自動的に用意する
-
saveAndFlushメソッド
- 引数のエンティティを永続化する
-
テンプレートの作成
- index.htmlを作成します
- 下記のコードを追加します
<!DOCTYPE html> <html> <head> <title>top page</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"> </head> <body class="container"> <h1 class="display-4 mb-4" th:text="${title}"></h1> <p th:text="${message}"></p> <form method="post" action="/" th:object="${formModel}"> <div class="mb-3"> <label for="name" class="form-label">FirstName</label> <input type="text" class="form-control" name="firstName" th:value="*{firstName}" /> </div> <div class="mb-3"> <label for="name" class="form-label"></label>LastName</label> <input type="text" class="form-control" name="lastName" th:value="*{lastName}" /> </div> <div class="mb-3"> <input type="submit" class="btn btn-primary" value="Create" /> </div> </form> <table class="table"> <thread> <tr> <th>firstName</th> <th>lastName</th> </tr> </thread> <tbody> <tr th:each="person : ${people}"> <td th:text="${person.firstName}"></td> <td th:text="${person.lastName}"></td> </tr> </tbody> </table> </body> </html>
ビルド
- 下記のコマンドを実行し、ビルドします
$ mvn clean install $ ls -l target/rest-db-0.0.1-SNAPSHOT.jar -rw-r--r-- 1 XXXX XXX 47717020 7 13 23:17 target/rest-db-0.0.1-SNAPSHOT.jar $
- 下記のコマンドを実行します
$ java -jar target/rest-db-0.0.1-SNAPSHOT.jar
確認
1.Test Connectionをクリックします。接続されました
Spring Bootを再起動
考察
今回は、H2データベースを使ってローカルに立てたDBに対して登録を行いました。次回は更新や削除を試します。
参考