Spring Boot × PostgreSQLによるデータ登録Tips.(解説付)

## はじめに
お疲れ様です！ @Keichan_15 です！

今回は **Spring Boot** と **PostgreSQL** を使用して、フォームに入力した値をDBに登録した後に、登録データを表示する機能を作成していきたいと思います。

過去にRailsを触れていたこともあって、比較的開発体験の良いSpring Boot。かなり気に入ってます。

それでは早速行っていきましょう！:muscle:

## 環境
- Windows11(Windows10でもほぼ同じ)
- Eclipse 2022-12 (4.26.0)
- Spring Boot
- PostgreSQL v15.3

## プロジェクト作成
最初にSpring Bootのプロジェクト作成から行います。導入方法は様々あるのですが、今回はSpring公式が [チュートリアル](https://spring.pleiades.io/quickstart) として公開している **Spring Initializr** を使用していきます。

https://spring.pleiades.io/quickstart

`ファイル > 新規 > Springスターター・プロジェクト(Spring Initializr)` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/6744549d-a005-86c9-170f-a0ea19df07a2.png)

特段デフォルトで問題ありません。`次へ`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/3229ccc3-6902-29b9-7f68-3cb5eaf5fe09.png)


依存関係を追加します。デフォルトで追加されているものに加えて、以下3つの依存関係を追加します。

- `Thymeleaf`
- `PostgreSQL Driver`
- `Spring Data JPA`

特に`PostgreSQL Driver`と`Spring Data JPA`はPostgreSQLの接続に必要なので、選択漏れが無いようにしましょう。

※ちなみに余談ですが、ビルド・ツールはGradle or Mavenか問題、実際の所どちらが良いんでしょう。まだ私はGradleしか使用したことが無いので何とも言えないですが…。

https://qiita.com/MahoTakara/items/ff73338e218b656bedfa

少し脱線してしまいましたね…(-_-;) 気を取り直して。

プロジェクト作成後のディレクトリ構成は以下になります。

```
demo
│  .classpath
│  .gitignore
│  .project
│  build.gradle
│  gradlew
│  gradlew.bat
│  HELP.md
│  settings.gradle
│
├─.gradle
│  ├─7.6.1
│  │  │  gc.properties
│  │  │
│  │  ├─checksums
│  │  │      checksums.lock
│  │  │
│  │  ├─dependencies-accessors
│  │  │      dependencies-accessors.lock
│  │  │      gc.properties
│  │  │
│  │  ├─executionHistory
│  │  │      executionHistory.lock
│  │  │
│  │  ├─fileChanges
│  │  │      last-build.bin
│  │  │
│  │  ├─fileHashes
│  │  │      fileHashes.lock
│  │  │
│  │  └─vcsMetadata
│  ├─buildOutputCleanup
│  │      buildOutputCleanup.lock
│  │      cache.properties
│  │
│  └─vcs-1
│          gc.properties
│
├─.settings
│      org.eclipse.buildship.core.prefs
│
├─bin
│  ├─main
│  │  │  application.properties
│  │  │
│  │  ├─com
│  │  │  └─example
│  │  │      └─demo
│  │  │              DemoApplication.class
│  │  │
│  │  └─templates
│  └─test
│      └─com
│          └─example
│              └─demo
│                      DemoApplicationTests.class
│
├─gradle
│  └─wrapper
│          gradle-wrapper.jar
│          gradle-wrapper.properties
│
└─src
    ├─main
    │  ├─java
    │  │  └─com
    │  │      └─example
    │  │          └─demo
    │  │                  DemoApplication.java
    │  │
    │  └─resources
    │      │  application.properties
    │      │
    │      ├─static
    │      └─templates
    └─test
        └─java
            └─com
                └─example
                    └─demo
                            DemoApplicationTests.java
```

また、依存関係が問題無く追記されているかを`build.gradle`で確認します。

```gradle:build.gradle
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'org.postgresql:postgresql'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
```
上記のようになっていればSpring Bootの導入は完了です。お疲れ様でした。

次にPostgreSQLの準備を行います。

## PostgreSQLの導入
PostgreSQLをまだダウンロードしていない方は、[EDB](https://www.enterprisedb.com/downloads/postgres-postgresql-downloads) からダウンロードしましょう。

https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/74798682-1248-5757-1860-5ce1bcbbd315.png)

今回は `Windows x86-64` 最新版の `v15.3` をダウンロードしました。OSによってはサポート外の場合や、ダウンロードリンクが別ページに記載されている場合があるため、注意して確認してください。

PostgreSQLのダウンロード方法については本記事の主題から逸れてしまうため、割愛させて頂きます。

日本PostgreSQLユーザー会が紹介している [インストールガイド](https://lets.postgresql.jp/map/install) や、下記の記事などが参考になるかと思います。

https://qiita.com/tom-sato/items/037b8f8cb4b326710f71

PostgreSQLのダウンロードが完了したら、早速CRUDのCであるデータ登録用のDBを準備していきましょう！

## DB準備
まずは本記事用のDBを構築します。

個人的に、最初はCLIで黒い画面と睨めっこしながら進めていく方が勉強になると思います。以下の記事などがそうです。

https://www.javadrive.jp/postgresql/database/index4.html

ただ今回は手っ取り早く構築したいので、便利なGUIである`pgAdmin4`を使用します。
後に`pgAdmin4`を使用する理由が分かります。（笑）

`PGAdmin4` はpostgreSQLをデフォルトでダウンロードした場合、 `C:\Program Files\PostgreSQL\15\pgAdmin4\runtime` にexeが存在しています。

exeを実行し、`pgAdmin4`を開くとパスワードの入力が求められますので、インストール時に設定したパスワードをここで入力してください。

以下のような画面が表示されていればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/06d9462a-7d82-0956-50a8-7e144f928da6.png)

このように、視覚的にDBを操作できる & UIが綺麗なので、個人的にはおススメですね。
特段CLIにこだわりがあったり、勉強の一環でコマンド打ちたかったりって方を除き、使うべきなのでは無いかなと。

次にデータベースを作成します。今回は `testdb` という名前のデータベースを作成します。

左の`Object Explorer`からDatabasesをクリックし、 `右クリック > Create > Database...` と進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/81f20851-ed7e-2428-90c6-5eb93c97d185.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/b06d2dcb-549d-bdd7-9c56-5e3ca0672803.png)

Databaseの項目に `testdb` と入力し、右下の `Save` をクリックすればデータベースが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/73393013-9878-cf59-0664-d3a34e0110e2.png)

問題無く保存できると`Object Explorer`のdatabases内に`testdb`が追加されていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/71c6af43-7e18-8804-ffb4-ebcd92d6a0fa.png)

これでDB作成は完了です！お疲れ様でした。次はテーブルとカラムを作成していきましょう！

## テーブル&カラム作成
まず、登録したデータを保持するための `forums` テーブルと、各データを保持するためのカラムを作成します。
`Object Explorer`の`testdb`を右クリックし、`Query Tool`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/ddb8c2fd-fbab-d87f-142c-7b52599bde81.png)

以下のSQL文を実行してください。

```sql:PostgreSQL
create TABLE forums (
  id serial primary key,
  title varchar(20),
  body varchar(100)
);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/a71dca3d-0c7e-884e-8d6f-0fde0149442c.png)

このような表記が出ればテーブルが作成できています。

画面に反映させるために`Refresh...`を選択します。これも`testdb`を右クリックすると出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/f68fd1da-2f94-a51e-8d39-62be67371485.png)

以下のように追加したテーブルが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/09f3d659-19eb-d3f2-9f33-ca60c7abc100.png)

ここで今回登録した各カラムについて簡単にまとめておきます。
- `id` : AUTO INCREMENTによる自動採番
- `title` : 投稿の「タイトル」を保持するカラム。文字数上限は20文字。
- `body` : 投稿の「本文」を保持するカラム。文字数上限は100文字。

次にカラムが追加されているかも確認してみましょう。

`lists`を右クリックすると `View/Edit Data > All Rows` を選択すると、テーブル内の全てのデータを表示することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/88d0c7d4-8652-58fe-79d3-e50452cd697c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/9e6f7ece-b16d-8ef5-84af-fcfcb9c86626.png)

現在はテーブルとカラムを定義しただけなので、写真のようにまっさらな状態になっています。
イメージはこのテーブルの各カラムに対して、Spring Boot側で作成したフォームより入力された値が格納されるようになります。

これでテーブルとカラムの作成は完了です。

最後にSpring Bootの`application.properties`を編集します。

```properties:src/resources/application.properties
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password="インストール時に決めたパスワード"
spring.jpa.open-in-view=True
```

この設定を行わないとSpring BootとpostgreSQLが接続できないので記入漏れが無いようにしましょう。
```properties
spring.datasource.password="インストール時に決めたパスワード"
```
パスワードはご自身で決めたものに変更してくださいね。:relaxed:

## 実装
いよいよSpring Bootの実装に入っていきます。
Spring Bootの詳しい内容については今後別記事でまとめる予定ですが、初めて触る方に向けて適宜解説を挟んでいきますので、分かりにくい等あればコメント頂けると幸いです。

今回は**同期通信**によるデータ登録のTipsを説明します。非同期通信(Ajax × jQuery)によるデータ登録については今後、別記事でまとめる予定です。

### :writing_hand:(寄り道)MVCモデルって？？

まず、Spring Bootを扱う上で大切な概念に**MVCモデル**があります。Ruby on RailsなどのWebフレームワークを使用したことがある方はお馴染みですね。

MVCモデルは各頭文字である **M(Model) V(View) C(Controller)** に分けてコードを管理するものです。

- **Model** : データベースとのやりとりやシステム内のデータ処理を担当
- **View** : 画面表示を担当
- **Controller** : ViewとModelの動作制御を担当(いわば仲介役)

MVCモデルを採用することにより、**役割ごとにファイルが独立しているため、保守性や開発効率向上に繋がる**ことがメリットとして挙げられています。

### ◎Model作成
最初にシステムの根幹ともいえるモデルから作成していきましょう。

今回作成するモデルは`Forum.java`になります。

```java:src/main/java/com/example/demo/model/Forum.java
package com.example.demo.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;

@Data
@Entity
@Table(name = "forums")
public class Forum {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id")
	private Integer id;
	@Column(name = "title")
	private String title;
	@Column(name = "body")
	private String body;
}
```

#### :speaking_head: 解説

まずJavaを使用して実装したことが無い方は、おそらく以下の表記に混乱されていると思います。
```java
@Data
@Entity
@Table
@Id
@GeneratedValue
@Column
```

これは**アノテーション**と呼ばれています。アノテーションとは直訳すると**注釈**という意味で、ソースコードにアノテーションを加えることによってプログラムの動作を変更したり、Spring Bootを始めとするframeworkに対して処理を指示したりすることができます。

例えば`@Data`ですが、このアノテーションはコンパイル時に以下のメソッドを自動生成します。
- setter()
- getter()
- toString()
- equals()
- hashCode()

特に上2つの`getter`,`setter`の表記を行わなくて良い点は、

- 開発者側も実装負担が減る
- ソースコードの可読性向上

にも繋がるので、アノテーションを使わない手はないといえるでしょう。

1つ1つのアノテーションを詳しく解説するのは本記事の主題から逸れるため省略します。
以下のサイトでアノテーションの一覧がまとめられています。非常に便利…。:relaxed:

https://learning-collection.com/spring-boot%E3%81%A7%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E4%B8%80%E8%A6%A7/

以下、各アノテーションや実装内容をコメントで付記しましたので、学習にお役立てください。
```java:src/main/java/com/example/demo/model/Forum.java
package com.example.demo.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;

// getter(), setter()を自動生成するアノテーション
@Data
// JPAのエンティティであることを示すアノテーション
@Entity
// エンティティに対応するテーブル名を指定。 "forums"部分はPostgreSQLで作成したテーブル名
@Table(name = "forums")
public class Forum {

    // エンティティの主キーを指定。今回であれば "id" カラムになる
	@Id
    // オートインクリメント。主キー "id" の値を自動採番する
	@GeneratedValue(strategy = GenerationType.IDENTITY)

    // カラムに名前を付与
	@Column(name = "id")
	private Integer id;

	@Column(name = "title")
	private String title;

	@Column(name = "body")
	private String body;
}
```

</details>

これでModelの実装は完了です！

### ◎Controller作成

次にControllerを作成していきます。

まず `ForumController`の作成を行います。

```java:src/main/java/com/example/demo/controller/ForumController.java
package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.Forum;
import com.example.demo.service.ForumService;

@Controller
public class ForumController {

    // 特定のアノテーションを付与したクラスのインスタンスを使用可能にする(依存性注入・DI) 
	@Autowired
	ForumService service;

	// トップページ(フォームがある画面)
    // HTTPリクエストの"GET"を受け付けるメソッドに付与するアノテーション
	@GetMapping("/")
	public String top(Model model) {
		model.addAttribute("forum", new Forum());
		return "top";
	}

	// データベースへの登録
    // HTTPリクエストの"POST"を受け付けるメソッドに付与するアノテーション
	@PostMapping("/create")
	public String saveForum(@ModelAttribute Forum forum, Model model) {

        // serviceクラスのinsertメソッドを呼び出し、DBに入力値を登録
		service.insert(forum);
		return "result";
	}

}
```

#### :speaking_head: 解説
今回登場したアノテーションは `@Autowired` `@GetMapping` `@PostMapping` になります。

中でも`@Autowired`についてですが、これは **DI(依存性注入)** を使用しています。特定のアノテーション(今回であれば@Serviceや後述の@Repository)を付与したクラスのインスタンスは、`@Autowired`を付与したフィールド変数などによって取得することができます。

次にトップページを表示するための`top`メソッドについて見ていきましょう。

```java
	@GetMapping("/")
	public String top(Model model) {
		model.addAttribute("forum", new Forum());
		return "top";
	}
```
`@GetMapping` によって、引数に指定しているURLにGETのHTTPリクエストが送られると、このメソッドが処理される仕組みになっています。`ex)localhost:8080/` にアクセス

`model.addAttribute("forum", new Forum());`はViewに値を渡すために使用します。
`addAttribute`の引数の設定方法ですが、**第1引数**に**Viewで使用する変数名**、**第2引数**に**Viewに渡したい値**を設定します。

今回であれば`forum`という変数には`Forum`クラスの空インスタンスが格納されており、これがViewのオブジェクト部分(後述のViewで紹介)に設定されることで、フォームの値を格納することができるようになります。

そして戻り値に `top` と指定していますが、この**戻り値の名前がViewのファイル名**になります。ポイントです。

流れのイメージをまとめると、
```
1. ルートパスにHTTPリクエスト(GET)が送られる
2. model.addAttributeでViewにフォームの空インスタンスを渡す
3. top.htmlを表示する
```
となります。こうすることで`top.html`でフォームを作成することができるんですね。

次にDB登録に必要なメソッドである`saveForum`を見ていきます。

```java
	@PostMapping("/create")
	public String saveForum(@ModelAttribute Forum forum, Model model) {

		service.insert(forum);
		return "result";
	}
```
ほとんどは先に挙げた`top`メソッドと変わりはありません。新たに登場した内容だけ紹介します。

- `@ModelAttribute`
`saveForum`メソッドの引数に`@ModelAttribute`のアノテーションが付与されています。
このアノテーションが付与されることにより、フォームで入力した値を受け取ることができるようになります。
引数の`forum`は、後述の`top.html`の`View`で作成したフォームの**オブジェクト**部分に入っているデータになります。

以下の`form`タグ内にある`th:object`の`forum`になります。
Viewの説明は後ほど詳しく行いますので、フォームで入力された値を受け取っているということを認識して頂ければ問題ありません！

```html
<form th:action="@{/create}" th:object="${forum}" method="post">
```

- `service.insert(forum);`
ここではServiceクラスのinsertメソッドを呼び出しています。前述のDI(依存性注入)によって呼び出すことができる仕組みです。
`insert()`の引数にフォームに入力された値が格納されているオブジェクトを設定することで、DBへ登録処理を行うことができます。
`insert()`メソッドの詳しい内容についても、後ほどServiceクラスの章で説明します。

DBへの登録処理が完了したら、`result.html`に遷移するように設定しています。

コントローラーの説明は以上です。難しいですね…:cry:

### ◎Viewの作成
続いてViewを作成します。

Spring BootではViewファイルを `src/resources/templates`配下に置くことで、画面を表示することができます。

まずフォーム画面を表示するためのトップページを作成します。

```html:src/resources/templates/top.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">

<head>
	<title>Index</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>

<body>
	<h2>【New Post】</h2>
	<form th:action="@{/create}" th:object="${forum}" method="post">

		<label>Title</label>
		<p><input type="text" th:field="*{title}" /></p>

		<label>Body</label>
		<p><textarea id="form" th:field="*{body}"></textarea></p>
		<p><input type="submit" value="送信" id="button" /></p>
	</form>
</body>

</html>
```

また、投稿内容を表示する画面も実装します。

```html:src/resources/templates/result.html
<!DOCTYPE HTML>
<html>

<head>
	<title>Result View</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>

<body>
	<div>
		<p>[[${forum.title}]]</p>
		<p>[[${forum.body}]]</p>
		<p><a href="http://localhost:8080/">一覧画面へ</a></p>
	</div>
</body>

</html>
```

#### :speaking_head: 解説
まずトップページから見ていきます。

今回はテンプレート・エンジンに`thymeleaf`を使用しています。
```html
<html xmlns:th="http://www.thymeleaf.org">
```
ここで`thymeleaf`の属性を`th`とし、名前空間を宣言して利用しています。

フォーム関連も`thymeleaf`を使用することで簡潔に実装が可能です。

```html
<form th:action="@{/create}" th:object="${forum}" method="post">
```
| th:action | th:object | method |
|:-:|:-:|:-:|
| フォームのアクションを設定(Controller側で使用)  | ${}内のオブジェクトにフォーム入力値が格納  | HTTPメソッドを指定  |

また、フォーム入力部分は`th:field`を使用することで、オブジェクトのフィールドに値を格納します。
```html
<p><input type="text" th:field="*{title}" /></p>
<p><textarea id="form" th:field="*{body}"></textarea></p>
```
ここで言うフィールドは、モデルである`Forum.java`内のフィールドを指しています。

```java:src/main/java/com/example/demo/model/Forum.java
// フィールド
@Column(name = "id")
private Integer id;

@Column(name = "title")
private String title;

@Column(name = "body")
private String body;
```

以上がトップページの実装になります。

続いて、結果表示画面について見ていきます。

```html
<p>[[${forum.title}]]</p>
<p>[[${forum.body}]]</p>
```
薄々お気付きかとは思いますが、上記の部分で入力した内容をそれぞれ表示しています。

以上がViewの実装になります。意外とシンプルでしたね。

### ◎Repository作成
次にRepositoryを作成します。
```java:src/main/java/com/example/demo/repository/ForumRepository.java
package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.demo.model.Forum;

@Repository
public interface ForumRepository extends JpaRepository<Forum, Integer> {
}
```
`JpaRepository`を継承したインターフェースを作成し、データベースを操作します。
`JpaRepository`を継承することにより、データ操作に関するCRUD(作成・取得・更新・削除)のメソッドを自動で生成してくれます。便利ですこと。

次にServiceを作成します。

### ◎Service作成
```java:
package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.model.Forum;
import com.example.demo.repository.ForumRepository;

import jakarta.transaction.Transactional;

@Service
@Transactional
public class ForumService {

	@Autowired
	ForumRepository repository;

	// データベースよりフォーラム(掲示板)の一覧を取得
	public List<Forum> findAll() {
		return repository.findAll();
	}

	// データベースに値を登録
	public void insert(Forum forum) {
		repository.save(forum);
	}
}

```

#### :speaking_head: 解説
今回新たに登場したアノテーションから見ていきましょう。

`@Service` アノテーションはこのクラスがサービスクラスであることを示しています。
また、`@Transactional`を付与することでDBのトランザクション制御を行います(今回のような小規模なアプリには必要性皆無)

次にデータベース操作系のメソッドについてです。
`repository.findAll();` では、`@Autowired`で作成したForumRepositoryのインスタンスを使用して、レコードの全件取得を行っています。**登録しているデータを一覧表示したい場合**などに使用します。今回は使いません。

`repository.save(forum);`では、フォーム入力値が格納されたオブジェクトを引数に設定して、DBへ登録します。

Serviceの実装&解説は以上です。これで実装全てが完了しました。

最終的なツリーを下記に記載しておきます。

```
demo
│  .classpath
│  .gitignore
│  .project
│  build.gradle
│  gradlew
│  gradlew.bat
│  HELP.md
│  settings.gradle
│
├─.gradle
│  ├─7.6.1
│  │  │  gc.properties
│  │  │
│  │  ├─checksums
│  │  │      checksums.lock
│  │  │      md5-checksums.bin
│  │  │      sha1-checksums.bin
│  │  │
│  │  ├─dependencies-accessors
│  │  │      dependencies-accessors.lock
│  │  │      gc.properties
│  │  │
│  │  ├─executionHistory
│  │  │      executionHistory.lock
│  │  │
│  │  ├─fileChanges
│  │  │      last-build.bin
│  │  │
│  │  ├─fileHashes
│  │  │      fileHashes.lock
│  │  │
│  │  └─vcsMetadata
│  ├─buildOutputCleanup
│  │      buildOutputCleanup.lock
│  │      cache.properties
│  │
│  └─vcs-1
│          gc.properties
│
├─.settings
│      org.eclipse.buildship.core.prefs
│
├─bin
│  ├─main
│  │  │  application.properties
│  │  │
│  │  ├─com
│  │  │  └─example
│  │  │      └─demo
│  │  │          │  DemoApplication.class
│  │  │          │
│  │  │          ├─controller
│  │  │          │      ForumController.class
│  │  │          │
│  │  │          ├─model
│  │  │          │      Forum.class
│  │  │          │
│  │  │          ├─repository
│  │  │          │      ForumRepository.class
│  │  │          │
│  │  │          └─service
│  │  │                  ForumService.class
│  │  │
│  │  └─templates
│  │          result.html
│  │          top.html
│  │
│  └─test
│      └─com
│          └─example
│              └─demo
│                      DemoApplicationTests.class
│
├─gradle
│  └─wrapper
│          gradle-wrapper.jar
│          gradle-wrapper.properties
│
└─src
    ├─main
    │  ├─java
    │  │  └─com
    │  │      └─example
    │  │          └─demo
    │  │              │  DemoApplication.java
    │  │              │
    │  │              ├─controller
    │  │              │      ForumController.java
    │  │              │
    │  │              ├─model
    │  │              │      Forum.java
    │  │              │
    │  │              ├─repository
    │  │              │      ForumRepository.java
    │  │              │
    │  │              └─service
    │  │                      ForumService.java
    │  │
    │  └─resources
    │      │  application.properties
    │      │
    │      ├─static
    │      └─templates
    │              result.html
    │              top.html
    │
    └─test
        └─java
            └─com
                └─example
                    └─demo
                            DemoApplicationTests.java
```

最後に動作に問題が無いか確認していきましょう！

## 動作確認
まずサーバーを起動します。サーバー起動はBootダッシュボードから実行できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/df4236e0-96e6-ac69-04c3-00a749796b7f.png)

コンソールに以下のような表記が出れば起動完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/df5da2b5-37aa-5b65-3a43-250bb4afdb89.png)

`localhost:8080`にアクセスします。以下のようなページが表示されると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/202e3b3c-6f92-9787-a57d-fb917d64faa0.png)

フォームに値を入力して`送信`ボタンを押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/98d51bb3-889c-3be2-17e7-fb84116a8373.png)

以下の画面が表示されていればOKです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/7e191dcf-d2c3-b001-4ea8-6a76e8b6bdad.png)

DBにも問題無くデータが登録されているか確認しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/62ccc027-70c5-1131-2d07-647e96118ed1.png)

問題無さそうです！:muscle:

以上でSpring Boot × PostgreSQLによる登録機能が完成です。お疲れ様でした！

## 参考

https://qiita.com/mi0/items/7e63f3212091c3786370

https://uha-blog.com/java/spring-boot-postgresql/

https://www.zunouissiki.com/spring-boot-register-postgressql/

https://learning-collection.com/spring-boot%E3%81%A7%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E4%B8%80%E8%A6%A7/

## おわりに
いかがでしたでしょうか。
今回はSpring BootとPostgreSQLを使用して、最低限のデータ登録機能を実装しました。

実際初めてSpring Bootに触れたのですが、冒頭に述べたようにRailsなどのWebフレームワークと似通っていることもあって、比較的すんなり理解することができました。
~~ただ最近はもっぱらNext.jsとGoとDockerを弄ってるので当分触らなくても良いかなあ~~

是非皆さんもSpring Boot使っちゃいましょ～～！:v: