SpringBoot + MySQL でTodoリストを作る！CRUDの実装(Read編)

# はじめに

今回は、**「SpringBootでMySQLからデータを取得して、Thymeleafを用いて画面に表示させる」**をゴールとしています。

SpringBootを学び始めた方、復習をしたい方に向けて学んだ事を共有します。

##開発環境

```
OS: macOS Mojave(バージョン 10.14.6)
```

```
$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
```

```
$ mvn -version
Maven home: /usr/local/Cellar/maven/3.6.3_1/libexec
Java version: 15.0.2, vendor: N/A, runtime: /usr/local/Cellar/openjdk/15.0.2/libexec/openjdk.jdk/Contents/Home
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.6", arch: "x86_64", family: "mac"
```

```
$ spring --version
Spring CLI v2.3.1.RELEASE
```

```
$ mysql --version
mysql  Ver 8.0.23 for osx10.14 on x86_64 (Homebrew)
```

# プロジェクトの作成(pom.xmlの編集)

[Spring initializr](https://start.spring.io/) でサクッとプロジェクトを作成します。



依存関係は以下の通りです。

```pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>todolist</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>todolist</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	
	<dependencies>

		<!-- テンプレートエンジン -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<!-- RESTfulを含んだWebアプリケーションライブラリの利用 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- ファイルの変更を検知すると自動で再起動する -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>

		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

		<!-- @Dataアノテーションを付与する事で,getter,setter等を自動生成してくれる -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<!-- テスト用 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- DBとJavaオブジェクトやり取りを行う。 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

```

# MySQLと接続

いきなりターミナルで`mvn spring-boot:run`を打ち込んで起動しようとしても出来ません。

```terminal:terminal
$ mvn spring-boot:run

~以下略~

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class
```


##1.DBを作成、テストデータの作成

まずMySQLでデータベースを作成します。

```sql:データベース作成
CREATE DATABASE spring_todolist_qiita;
```

```sql:mysql
mysql> show databases;
+-----------------------+
| Database              |
+-----------------------+
| information_schema    |
| mysql                 |
| performance_schema    |
| spring_todolist_qiita | -- ←作成完了
| sys                   |
+-----------------------+
```

テーブルを作成してデータを追加します。

```sql:テーブル作成
mysql> use spring_todolist_qiita;

mysql> create table if not exists todolist (
  id integer not null auto_increment,
  content text not null,
  done boolean not null default 0,
  primary key (id)
);
```

データを何個か作っておきます。

```sql:データの追加
mysql> insert into todolist (content) values ("卵を買う");
--以下略--
```

##2.SpringBootにMySQLの情報を定義する

application.propertiesにMySQLに接続するため記述します。

```application.properties
# 接続先のDB名を設定
spring.datasource.url=jdbc:mysql://localhost/spring_todolist_qiita

# 接続しているDBの username と passwordを設定
# 〇〇と△△はご自身のusername,passwordを記載してください
spring.datasource.username=〇〇
spring.datasource.password=△△

# MySQL用JDBCドライバの設定
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
```

再度ターミナルで`mvn spring-boot:run`を打ち込むと、起動はするようになります。


#SpringBootとMySQL間のやり取りの実装

TodolistApplication.javaと同じ階層に各フォルダを作成して、それぞれ中身を実装していきます。

![スクリーンショット 2021-03-13 10.53.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/f5f9b89f-00ea-ddb9-80b3-b95365530b35.png)



##1.エンティティモデルの作成

`@Entity`でエンティティクラスである事を宣言し、データベースのテーブルとマッピング。

`@Table(name = "todolist")`は、エンティティクラスとマッピングされるDBのテーブル名を指定する。

`@Id`は、主キーである事を、`@GeneratedValue(strategy = GenerationType.IDENTITY)`は、主キーが自動採番されるよう宣言。



```java:Todo.java
package com.example.todolist.Model;

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

import lombok.Data;

// データを格納するクラス(DBへ登録、更新時の入れ物)
@Entity
@Data
@Table(name = "todolist")
public class Todo {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;

  private String content;

  private boolean done;
}
```

##2.DBにアクセスするRepositoryを作成

データベースから値の取得、更新などのメソッドが定義されている`JpaRepositoryインターフェース`を継承したインターフェースを用意する。

`@Repository`でDBアクセスのクラスであると宣言、DIコンテナに登録される。

```java:TodoRepository.java
package com.example.todolist.Repository;

import org.springframework.stereotype.Repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.todolist.Model.Todo;

// DBにアクセスするためのインターフェース
@Repository
public interface TodoRepository extends JpaRepository<Todo, Integer> {
}
```

##3.具体的な処理を行うServiceを作成

`@Service`でサービスクラスである事を宣言、DIコンテナに登録される。

`@Autowired`で、DIコンテナに登録されているTodoRepositoryのインスタンスを生成して返してくれている。



```java:TodoService.java
package com.example.todolist.Service;

import java.util.List;

import com.example.todolist.Model.Todo;
import com.example.todolist.Repository.TodoRepository;

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

// DBとの具体的な処理(データの取得、新規作成など)を記述するクラス
@Service
public class TodoService {
  
  @Autowired
  TodoRepository todoRepository;

  // todolistを全件取得
  public List<Todo> searchAll() {
    return todoRepository.findAll();
  }
}
```

#取得したデータを画面に表示させる

Controllerを用意してDBからデータを取得し、Viewに送って画面に表示させます。

##1.Controllerを作成

`@Controller`でコントローラークラスである事を宣言。

`@Autowired`で、DIコンテナに登録されているTodoServiceのインスタンスを生成して返してくれている。


```java:TodoController.java
package com.example.todolist.Controller;

import java.util.List;

import com.example.todolist.Model.Todo;
import com.example.todolist.Service.TodoService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;


@Controller
public class TodoController {

  @Autowired
  TodoService todoService;
  
  @GetMapping("/")
  public String home(Model model) {
    List<Todo> allTodo = todoService.searchAll();
    model.addAttribute("allTodo", allTodo);
    return "home";
  }
}
```

`@GetMapping("/")`でlocalhost:8080にアクセスすると、homeメソッドが呼び出される。

`todoServiceのserarchAllメソッド`で、DBからデータを全件取得して`model.addAttribute`でViewにJavaオブジェクトを渡している。


##2.HTMLの作成

上記Controllerで`return "home"`としているので、home.htmlを作成する。

```html:home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>SpringTodoList</title>
</head>
<body>
  <div th:each="todo : ${allTodo}">
    <p th:text="${todo.content}"></p>
  </div>
</body>

</html>
```

Controllerから渡された`allTodo`はList型なので、
`th:each="todo : ${allTodo}"`のループを回して`todo`に一つずつデータを格納している。

`todo.content`でcontentを描画している。

#SpringBootの起動

MySQLのデータが画面に表示されているか確認します。

```terminal:terminal
$ mvn spring-boot:run
```

**localhost:8080**にアクセスしてみると...

![スクリーンショット 2021-03-13 11.27.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/6b7aa1c4-5d4c-18dc-f918-6e7dd2df8cb0.png)

無事表示されました。

#終わりに

CSSの記述もしていないので味気ないページですが、SpringBootとMySQLを接続してデータを表示させる事が出来ました。

ご自身の環境でも試してみてください。

次は新規登録の実装をしてみたいと思います。