4
4

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-03-17

はじめに

前回はフォームを用意してTodoの新規登録機能を実装しました。

今回は、「blooeanの値を変更してMySQLのデータを更新する」をゴールとしています。

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

        <!-- ORMのMyBatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </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>

        <!-- アノテーションを付与する事で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>

        <!-- バリデーション用 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</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>

booleanの値によって表示する領域を分ける

まずhtmlを編集します。
th:if="${!todo.done}"は、
todoのdoneの値がtrue/falseどちらか判別して、表示するかどうかを決めています。

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">
    <form method="POST" th:action="@{/}" th:object="${todo}">
      <p th:errors="*{content}" class="todo-error-message"></p>
      <input type="text" th:field="*{content}">
      <button type="submit">登録</button>
    </form>
  </div>


  <!-- 今回の変更点 -->
  <div class="flex">      
    <div class="incomplete">
      <h1>未完了</h1>
      <div th:each="todo : ${allTodo}">
        <!-- doneのフラグがfalseのものを表示 -->
        <div th:if="${!todo.done}">
          <!-- Controllerの @PostMapping(/done) と結びつける -->
          <form method="POST" th:action="@{/done}">
            <input type="hidden" name="id" th:value="${todo.id}" />
            <button type="submit"></button>
          </form>
          <p th:text="${todo.content}"></p>
        </div>
      </div>
    </div>

    <div class="complete">
      <h1>完了済み</h1>
      <!-- doneのフラグがtrueのものを表示 -->
      <div th:each="todo : ${allTodo}" th:if="${todo.done}">
        <p th:text="${todo.content}"></p>
      </div>
    </div>

  </div>
  <!-- ここまで -->

</body>

</html>

ここで丸いボタンを作成して、ボタンが押下されたらControllerの処理が走るようにします。
Todoのidを渡しているので、そのidbooleanの値を変更してDBを更新させる予定です。

<!-- Controllerの @PostMapping(/done) と結びつける -->
<form method="POST" th:action="@{/done}">
  <input type="hidden" name="id" th:value="${todo.id}" />
  <button type="submit"></button>
</form>
<p th:text="${todo.content}"></p>

staticフォルダにcssフォルダを作成して、その中にhome.cssを作成してレイアウトを整えます。

home.css
body {
  padding: 0;
  margin: 0;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 1.4rem;
}

h1 {
  text-align: center;
  margin: 20px 0 0 0;
}

p {
  display: inline-block;
}

.create-todo {
  margin: 20px 0 0 0;
  display: flex;
  justify-content: center;
}

.create-todo input {
  font-size: 1em;
  line-height: 1.2;
  border-width: 2px;
  border-style: solid;
  border-radius: 5px;
  padding: 0.5em 0.5em;
  width: 300px;
}

.create-todo button {
  font-size: 1em;
  line-height: 1.2;
  border-width: 2px;
  border-style: solid;
  border-radius: 5px;
  background-color: #008CBA;
  cursor: pointer;
  color: white;
  display: inline-flex;
  justify-content: center; /* コンテンツを水平方向に中央揃え */
  align-items: center; /* コンテンツを垂直方向に中央揃え */
  padding: 0.5em 1.2em;
}

.todo-error-message {
  color: red;
  text-align: center;
  font-size: 1.2rem;
}

/* 未完了、完了済みタスクエリア */
.flex {
  display: flex;
  justify-content: space-around;
  margin: 30px 0 0 0;
}

.incomplete {
  text-align: center;
  width: 400px;
  background-color: pink;
}

.incomplete form {
  display: inline;
}

.incomplete button {
  background-color: white;
  border-radius: 50%;
  height: 15px;
  width: 15px;
  cursor: pointer;
  display: inline-flex;
  justify-content: center; /* コンテンツを水平方向に中央揃え */
  align-items: center; /* コンテンツを垂直方向に中央揃え */
}

.complete {
  text-align: center;
  width: 400px;
  background-color: green;
}

Boolean型のgetter,setterを用意する

Lombok@Dataアノテーションを付与することで、自動でgetter,setterを作成してくれます。
ただBooleanの型の変数は、get〇〇,set〇〇と出来ません。

lombok.configを作成する

一番上の階層にlombok.configというファイルを作成し以下の様に記述します。

スクリーンショット 2021-03-17 13.16.19.png

lombok.config
lombok.getter.noIsPrefix=true

これでis〇〇でBooleanの変数を取得するようになっていましたが、get〇〇,set〇〇が使えるようになります。

Lombokの公式

findByIdメソッドの実装

idに応じたTodoを取得したいので、findById()メソッドを実装します。

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

import java.util.List;
import java.util.Optional;

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();
  }

  public void addTodo(Todo todo) {
    todoRepository.save(todo);
  }

  // 追加(idに応じたTodoを返却する)
  public Todo findById(Integer id) {
    Optional<Todo> updateTodo = todoRepository.findById(id);
    return updateTodo.get();
  }
}

findById()メソッドは、Optionalクラスで受け取らなければいけないためそのように受け取り、
中のTodoを取り出すには、get()メソッドを使用しています。

公式の説明

Controllerでupdate用メソッドの実装

Viewからidを受け取り先ほど実装したfindByIdメソッドを使用して、特定のデータを更新する処理を実装していきます。

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;
import org.springframework.web.bind.annotation.RequestParam;


@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());
    return "home";
  }

  @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";
    }

    todoService.addTodo(todo);
    return "redirect:/";
  }

  // 追加(未完了タスク一覧にある丸いボタンが押されたら、この処理が実行される)
  @PostMapping("/done")
  public String doneTodo(@RequestParam(name = "id") Integer todoId) {
    Todo updateTodo = todoService.findById(todoId);
    updateTodo.setDone(true);
    todoService.addTodo(updateTodo);
    return "redirect:/";
  }

}

動作確認

現在、CSSを適用させたのでこのようになっています。
スクリーンショット 2021-03-17 14.21.43.png

例えば、「猫のトイレ掃除」の横のボタンを押します。

スクリーンショット 2021-03-17 14.22.47.png

完了済みのエリアに移動しました!!!

終わりに

idに応じたデータを更新する実装も無事出来ました。
SpringBootにはメソッドを使用するだけで簡単にDBの値を更新する事ができる事が分かりました。

最後は削除機能を実装しようと思います。

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