4
3

More than 3 years have passed since last update.

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

Posted at

はじめに

前回は、DBから取得したデータを画面に表示させるところまで実装しました。

スクリーンショット 2021-03-13 11.27.00.png

今回は入力フォームと送信ボタンを用意して、「送信ボタンが押された時、フォームで入力された値をMySQLに登録する」をゴールとしています。

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

前回のRead編はこちら

開発環境

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
<?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>

依存関係の編集(pom.xml)

フォームで入力値の検証をしたいため、pom.xmlに新たに依存関係を追加します。

pom.xml
<!-- バリデーション用 -->
<dependency>
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

バリデーションの設定

Todo.javaに@NotNull@NotBlankというアノテーションを追加します。

null空白がDBに登録出来ないようにするためです。

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 javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

import lombok.Data;

// データベースから取得したデータを格納するクラス(登録、更新時の値を保持する)
// データベースの1行に対応した形になっている。
@Entity
@Data
@Table(name = "todolist")
public class Todo {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;

  // 追加
  @NotNull
  @NotBlank
  private String content;

  private boolean done;
}

フォームを作成

新規登録用のフォームを作ります。

th:objectはTodoオブジェクトをControllerから受け取っています。

th:fieldは、th:objectで受け取ったTodoオブジェクトの変数を指しています。

th:errorsは、フォームの入力値にエラーがあった場合に表示させるエラーメッセージです。

home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <link rel="stylesheet" type="text/css" th:href="@{css/home.css}">
  <title>SpringTodoList</title>
</head>
<body>

  <!-- 追加 -->
  <div class="create-todo">
    <!-- th:objectでControllerから送られてきたTodoオブジェクトを受け取っている -->
    <form method="POST" th:action="@{/}" th:object="${todo}">
      <!-- 入力値にエラーがあった時のみ表示 -->
      <p th:errors="*{content}" class="todo-error-message"></p>

       <!-- th:fieldでHTMLのid,name属性を作ってくれる -->
      <input type="text" th:field="*{content}">
      <button type="submit">登録</button>
    </form>
  </div>
  <!-- ここまで -->

  <h1>やること</h1>
  <div class="incomplete" th:each="todo : ${allTodo}">
    <p th:text="${todo.content}"></p>
  </div>

</body>

</html>

Serviceにメソッドを追加する

DBに新規登録するためにメソッドを追加します。

JpaRepositoryにはsaveメソッドが用意されており、引数で受け取ったエンティティを保存します。
TodoRepositoryJpaRepositoryを継承しているので使えます。

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;

  public List<Todo> searchAll() {
    return todoRepository.findAll();
  }

  // 追加(Todoを新たにDBに登録する)
  public void addTodo(Todo todo) {
    todoRepository.save(todo);
  }
}

Controllerでフォームから値を受け取る

登録ボタンが押された時にDBへ登録するためのメソッドを追加します。
@PostMapping("/")は先ほどhtmlのformに付与した、th:action="@{/}"と結びついています。

@Validは入力されたデータの検証をするためのアノテーションで、BindingResultは、エラーメッセージを格納するクラスです。

bindingResult.hasErrors()でエラーの有無で処理を分けています。

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

import java.util.List;

import javax.validation.Valid;

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.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;


@Controller
public class TodoController {

  @Autowired
  TodoService todoService;

  @GetMapping("/")
  public String home(Model model) {
    List<Todo> allTodo = todoService.searchAll();
    model.addAttribute("allTodo", allTodo);
    model.addAttribute("todo", new Todo()); // 追加:新しいTodoオブジェクトをviewに引き渡す(th:objectで受け取る)
    return "home";
  }

  // 追加(formのth:actionと結びついている)
  @PostMapping("/")
  public String createTodo(@Valid Todo todo, BindingResult bindingResult,Model model) {
    // 入力値にエラーがあった時
    if(bindingResult.hasErrors()) {
      List<Todo> allTodo = todoService.searchAll();
      model.addAttribute("allTodo", allTodo);
      model.addAttribute("todo", todo);
      return "home";
    }

    // エラーがなかった時は、Todoを新規登録する
    todoService.addTodo(todo);
    return "redirect:/";
  }  
}

動作確認

localhost:8080にアクセスすると、フォームと登録ボタンが表示されているはずです。(CSSは勝手に記述しました)

スクリーンショット 2021-03-16 13.06.40.png

適当に文字を入力して...

スクリーンショット 2021-03-16 13.10.03.png

登録ボタンを押下すると...

スクリーンショット 2021-03-16 13.10.28.png

新規登録され、画面に表示されました!!!

また、何も入力せずにorスペースだけ入力して登録ボタンを押すと...

スクリーンショット 2021-03-16 13.11.44.png

エラーメッセージが表示され、DBには登録されていません。

終わりに

SpringBootでサクッと入力値の検証、エラーメッセージの表示、フォームの値をDBに新規登録することが出来ました。

次は更新機能の実装をしてみたいと思います。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3