Spring Boot + Spring Data JPA ～サンプルアプリ実装～

#Spring Data JPAについて
Spring Data JPA とは、Javaの標準仕様である JPA（Java Persistence API）でDBアクセスができるライブラリ／フレームワークです。Spring Data JPA を使うと簡単にDBアクセスが出来ます。
JavaのDBアクセスといえば「JDBC」がよく使われますが、「JPA」も利用する機会が増えてきています。

Spring Data JPA は、内部実装にHibernate（ハイバーネート）を使用しています。
Hibernateは ORM（オブジェクト関係マッピング）ライブラリです。ORMはJavaクラスとDBテーブルを上手く繋ぎ合わせてくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/71ce0e68-cd4f-0336-54a1-96c0d7aefd35.png)

Hibernateについて
ORMは一般的に「**O/Rマッパー**」と呼ばれます。O/Rマッパーは、Object指向における Object と Relationalデータベース(RDB)を 巧妙に関連付け(マッピング)するためのツールです。O/Rマッパーを利用すると例えば下記のコーディングを省力化できます。

- データベースへ問合せの結果セットからのオブジェクトの生成
- データベースのスキーマ変更に伴うプログラムの変更

Spring Data JPAを利用する場合、JDBCを意識する事はありませんが、Hibernateも内部ではSQLを生成し、JDBCを使用してDB接続を行っています。その為、JDBCはDB接続の基盤技術と言えます。

#開発環境
サンプルアプリケーションの作成は、下記環境に[Spring Tool Suite(STS)の導入](https://qiita.com/t-shin0hara/items/d60116ab299a4dc8a9d0)及び、[H2 databaseのインストール](https://qiita.com/t-shin0hara/items/44a7ed8bd736aa470e11)が完了している事を前提とします。

| 種別               | プロダクト                  |
|:-------------------|:---------------------------|
| JVM                | Java 11                    |
| OS                 | Windows 10 64bit           |

#サンプルアプリケーションの作成
Spring Bootを利用して実際に簡単なアプリケーションを作成します。作成するのは、以下の画面のようにコメントの一覧表示・登録・削除の機能を持つコメント投稿アプリです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/45b00f74-c139-9882-268d-327335a46e45.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/825787ef-b7ff-979a-a2f0-ad07eb845cd7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/985fe56c-0898-82a6-696f-63a0fcf88a32.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/c3d970d1-ca7e-4280-4d5e-bfbf0e24e55b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/79014d89-0dcf-55f1-acc2-4e4d638f738c.png)

アプリ作成完了時のフォルダ構成は下記となります。
![structure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/006a273c-e86c-a6c1-55d8-66026ab0fd0d.png)


# 1. 新規プロジェクト作成
Spring Tool Suite(STS)のメニューから、[ファイル] -> [新規] -> [Spring スターター・プロジェクト] を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/783ee449-7246-2e3e-722b-2405ff94b9fa.png)

[新規 Spring スターター・プロジェクト]ダイアログで、以下を入力して[次へ]ボタンを押下します。
- 名前：spring-jpa2
- Java バージョン：11
![structure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/f166a39b-75f4-339f-9bc0-a984e7b27276.png)

依存関係で以下にチェックを入れて[完了]ボタンを押下します。
▼開発ツール
　・**Spring Boot DevTools**
　・**Lombok**
▼I/O
　・**検証**
▼SQL
　・**Spring Data JPA**
　・**H2 Database**
▼テンプレート・エンジン
　・**Thymeleaf**
▼Web
　・**Spring Web**
![structure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244937/b0814a6c-6904-3873-0ea6-63a07cf6e7e8.png)

# 2. Lombokの導入設定
Springスターター・プロジェクト作成時に依存関係で**Lombok**を指定しただけでは、作成するアプリケーション実行時に**Lombok**が正常動作しない為、以下のとおりプロジェクトフォルダ直下の**「pom.xml」**を修正してください。

```xml:pom.xml（変更前）
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
```
```xml:pom.xml（変更後）
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.8</version>
			<scope>provided</scope>
		</dependency>
```

# 3. H2 Databaseの設定
src/main/resources/application.propertiesに以下のとおりH2 Databaseに関する設定を追加します。

```properties:application.properties
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.generate-unique-name=false
spring.jpa.show-sql=true

spring.datasource.username=sa
spring.datasource.password=
```
```text:参考情報
　spring.datasource.url・・・DBの接続URLを設定します。
　spring.datasource.generate-unique-name・・・trueの場合、ランダムなデータソース名を生成します。H2コンソールで接続する場合は、接続先を固定するためfalseを設定します。
　spring.jpa.show-sql・・・trueにすると内部で生成しているSQLをコンソールに出力できます。
```

# 4. モデルの作成
[com.example.demo]で右クリック -> [新規] -> [クラス] を選択する。
[新規Javaクラス]ダイアログで、以下を入力して[完了]ボタンを押下します。
- パッケージ：**com.example.demo.model**（modelを追加）
- 名前：**Comment**

Comment.javaを以下のとおり編集します。

```java:Comment.java
package com.example.demo.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
public class Comment {
	
	@Id
	@GeneratedValue
	private Long id;
	
	@NotBlank
	@Size(max = 40)
	private String content;

}
```

```text:参考情報
　@Entity・・・データの入れ物である「エンティティ(クラス)」であることを指定するアノテーションです。
　@Id・・・エンティティの主キーである事を指定するアノテーションです。
　@GeneratedValue・・・主キーの値を自動採番したい場合に指定するアノテーションです。@Idと一緒に使用します。
```

# 5. リポジトリの作成
[com.example.demo]で右クリック -> [新規] -> [インターフェース] を選択する。
[新規Javaインターフェース]ダイアログで、以下を入力して[完了]ボタンを押下します。
- パッケージ：**com.example.demo.repository**（repositoryを追加）
- 名前：**CommentRepository**

CommentRepository.javaを以下のとおり編集します。

```java:CommentRepository.java
package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.model.Comment;

public interface CommentRepository extends JpaRepository <Comment, Long> {

}
```

```text:参考情報
　JpaRepositoryを継承（extends）するだけで、そのリポジトリクラスはDBのCRUD(クラッド)操作※が可能となります。
　　※CRUDはCreate(Insert)/Read(Select)/Update/Deleteの略。
```

# 6. コントローラの作成
[com.example.demo]で右クリック -> [新規] -> [クラス] を選択する。
[新規Javaクラス]ダイアログで、以下を入力して[完了]ボタンを押下します。
- パッケージ：**com.example.demo.controller**（controllerを追加）
- 名前：**CommentController**

CommentController.javaを以下のとおり編集します。

```java:CommentController.java
package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org. springframework.validation. annotation. Validated;
import org. springframework.web.bind.annotation.GetMapping;
import org. springframework.web.bind.annotation.ModelAttribute;
import org. springframework.web.bind.annotation.PostMapping;

import com.example.demo.model.Comment;
import com.example.demo.repository.CommentRepository;

@Controller
public class CommentController {

	private final CommentRepository repository;

	//@Autowired ← コンストラクタが１つの場合、@Autowiredは省略できます
	public CommentController(CommentRepository repository) {
		this.repository = repository;
	}

	@GetMapping("/")
	public String getAllComments(@ModelAttribute Comment comment, Model model) {
		// COMMENTテーブル：レコード全件取得
		model.addAttribute("comments", repository.findAll());
		return "list";
	}

	@PostMapping("/add")
	public String addComment(@Validated @ModelAttribute Comment comment, BindingResult result, Model model) {
		model.addAttribute("comments", repository.findAll());
		if (result.hasErrors()) {
			return "list";
		}
		// COMMENTテーブル：コメント登録
		repository.save(comment);
		// ルートパス("/") にリダイレクトします
		return "redirect:/";
	}

	@GetMapping("/delete")
	public String deleteComment(@Validated @ModelAttribute Comment comment, BindingResult result, Model model) {
		model.addAttribute("comments", repository.findAll());
		// COMMENTテーブル：レコード削除
		repository.deleteById(comment.getId());
		// ルートパス("/") にリダイレクトします
		return "redirect:/";
	}
		 
}
```

```text:参考情報
　@Autowired・・・このアノテーションを付けると、Springが自動でインスタンスを生成しインジェクションしてくれます。
　repository.findAll()・・・データを全件取得するメソッドです。SQLの"select * from table_name"にあたります。指定データを取得する.findById(id)というメソッドもあります。
　repository.save(Object)・・・データを保存するメソッドです。SQLのINSERT、UPDATEにあたります。
　repository.deleteById(Object)・・・対象データを削除するメソッドです。SQLの主キー指定のDELETEにあたります。
```

# 7. Thymeleafテンプレートの作成
コメント投稿画面のThymeleafテンプレートを作成します。
[templates]で右クリック -> [新規] -> [その他] を選択する。
[新規]ダイアログで、[Web] -> [HTMLファイル] を選択して[次へ]ボタンを押下します。
[新規 HTML ファイル]ダイアログで、以下を入力して[完了]ボタンを押下します。
- ファイル名：**list.html**

list.htmlを以下のとおり編集します。

```html:list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>CommentApp</title>
</head>
<body>
  <h3>コメント投稿アプリ</h3>
  <div th:if="${comments.size() == 0}">
    投稿されたコメントはありません。
  </div>
  <table>
    <div th:each="comment : ${comments}" th:inline="text">
      <tr>
        <td><a th:href="@{/delete?(id=*{comment.id})}"><button>削除</button></a></td>
        <td>&nbsp;[[${comment.content}]]</td>
      </tr>
    </div>
  </table>
  <hr>
  <form th:action="@{/add}" th:object="${comment}" method="post">
    <input type="text" th:field="*{content}">
    <button>投稿</button><br><small style="color:red" th:errors="*{content}"></small>
  </form>
  <br>

</body>
</html>
```

```text:参考情報
　th:if・・・if文の条件式を書くことが出来ます。
　th:each・・・繰り返し処理を行います。
　th:each="comment : ${comments}"と記述すると、${comments}から1件ずつ取り出し、comment変数に格納できます。
```

# 8. Spring Bootアプリケーションの起動
H2 Databaseに接続していない場合は、H2 ConsoleでDBに接続してから下記手順を実施してください。
[SpringJpa2Application]で右クリック -> [実行] -> [Spring Boot アプリケーション] を選択する。
コンソールで起動を確認したら、ブラウザで **http://localhost:8080/** にアクセスします。

**参考書籍**
「Spring Boot 2.3 入門: 基礎から実演まで」(電子書籍)　原田 けいと／竹田 甘地／Robert Segawa著