LoginSignup
17
35

More than 5 years have passed since last update.

Spring Boot + Thymeleaf + MySQLでCRUDを実装する

Last updated at Posted at 2017-05-06

前回、以下の記事を書きました。
Spring Boot + ThymeleafでWEBアプリを動かす

今回は同様の構成で、REST型でWebアプリにアクセスしてDBのデータを操作します。一番最初に表示する画面でテーブルのレコードを一覧表示しておき、その画面からデータ登録、既存データの更新、既存データの削除を実施するようなアプリになります。
構成は前回の記事のものに加えて、DBにMySQLを利用します。なお本記事ではMySQLの構築手順は省略します。また、DB接続にO/Rマッパは利用せずJDBCのみを使っています。

Mac OS X 10.12
Java 1.8.0_92
Spring Tool Suite 3.8.4
Spring Boot 1.5.3
thymeleaf 2.1.5

API一覧

以下の通り5通りのAPIを作成します

NO METHOD url 動作
1 GET /sample/ テーブル全件参照
2 GET /sample/:id id指定した1件参照
3 POST /sample/ レコード登録
4 PUT /sample/:id 1レコード更新
5 DELETE /sample/:id 1レコード削除

共通部分

前回の記事で利用した「SampleController.java」に上記のAPIを構築します。MySQLにはuserというテーブルを作成して、テーブルに対してRESTでデータを操作します。

DB

CREATE DATABASE mysql CHARACTER SET UTF8;
CREATE TABLE user (
  id int AUTO_INCREMENT,
  name varchar(254)
);
INSERT INTO user (id, name) VALUES (1, "kusakarikai");

追加・修正ファイル
1.png

userテーブルの定義

com.example.User.java
package com.example;

public class User {
    private int id;
    private String name;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

ActionForm

com.example.UserForm.java
package com.example;

public class UserForm {
    private String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

ORマップ定義
ResultSet.next()をwhileでループさせると、最初の要素が読まれない事象が解決できずループの前に直接書いています。

com.example.UserMapper.java
package com.example;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;

public class UserMapper implements RowMapper<List<User>> {
    public List<User> mapRow(ResultSet rs, int rowNum)
     throws SQLException {
        List<User> list = new ArrayList<>();
        User tmp_user = new User();
        tmp_user.setId(rs.getInt("id"));
        tmp_user.setName(rs.getString("name"));
        list.add(tmp_user);
        while (rs.next()) {
            User user = new User();
            user.setId(rs.getInt("id"));
            user.setName(rs.getString("name"));
            list.add(user);
        }
        return list;
    }
}

DB接続の設定

src/main/resources/application.properties
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/DB名
spring.datasource.username=ユーザ名
spring.datasource.password=パスワード
spring.datasource.driver-class-name=org.gjt.mm.mysql.Driver

依存の設定

pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

1 GET /sample/

userテーブルのレコードを全件取得して、一覧表示します。

Controller

com.example.SampleController.java
@Autowired
private JdbcTemplate jdbcTemplate;

@RequestMapping(path = "/sample", method = RequestMethod.GET)
String index(Model model) {
    List<User> list = jdbcTemplate.queryForObject("select * from user", new UserMapper());
    model.addAttribute("list", list);
    return "sample/index";
}

template

src/main/resources/templates/sample/index.html
<table class="list">
  <tr>
    <th>ID</th>
    <th>名前</th>
  </tr>
  <tr th:each="list:${list}">
    <td th:text="${list.id}"></td>
    <td th:text="${list.name}"></td>
  </tr>
</table>

2 GET /sample/:id

userテーブルのレコードを1件取得します。

Controller

com.example.SampleController.java
@Autowired
private JdbcTemplate jdbcTemplate;

@RequestMapping(path = "/sample/{id}", method = RequestMethod.GET)
String show(Model model, @PathVariable("id") int id) {
    List<User> list = jdbcTemplate.queryForObject("select * from user where id = ? ", new Object[] { id }, new UserMapper());
    model.addAttribute("list", list);
    return "sample/index";
}

template
省略(NO1と同様)

3 POST /sample

入力をuserテーブルに登録します。登録後はNO1のAPIにリダイレクトすることで一覧を取得して画面に表示します。

Controller

com.example.SampleController.java
@Autowired
private JdbcTemplate jdbcTemplate;

@ModelAttribute
UserForm userForm() {
    return new UserForm();
}

@RequestMapping(path = "/sample", method = RequestMethod.POST)
String create(Model model, @ModelAttribute UserForm userForm) {
    jdbcTemplate.update("INSERT INTO user (name) values (?)", userForm.getName());
    return "redirect:/sample";
}

template

src/main/resources/templates/sample/index.html
<form method="post" name="create" action="/sample" accept-charset="UTF8">
    <input type="text" name="name"/>
    <input type="submit" value="新規登録" />
</form>

4 PUT /sample/:id

既存の登録内容を更新します。登録後はNO1のAPIにリダイレクトすることで一覧を取得して画面に表示します。

Controller

com.example.SampleController.java
@Autowired
private JdbcTemplate jdbcTemplate;

@ModelAttribute
UserForm userForm() {
    return new UserForm();
}

@RequestMapping(path = "/sample/{id}", method = RequestMethod.PUT)
String update(Model model, @ModelAttribute UserForm userForm, @PathVariable("id") int id) {
    jdbcTemplate.update("UPDATE user SET name = ? where id = ? ", userForm.getName(), id);
    return "redirect:/sample";
}

template

src/main/resources/templates/sample/index.html
<form method="post" action="/sample/:id">
    <input type="hidden" name="_method" value="put">
    <input type="text" name="name">
    <input type="submit">
</form>

5 DELETE /sample/:id

既存の登録内容を削除します。登録後はNO1のAPIにリダイレクトすることで一覧を取得して画面に表示します。

Controller

com.example.SampleController.java
@Autowired
private JdbcTemplate jdbcTemplate;

@RequestMapping(path = "/sample/{id}", method = RequestMethod.DELETE)
String destory(Model model, @PathVariable("id") int id) {
    jdbcTemplate.update("delete from user where id = ? ", id);
    return "redirect:/sample";
}

template

src/main/resources/templates/sample/index.html
<a href="javascript:void(0);" onclick="destory_func();">削除</a>
function destory_func() {
    var form = document.createElement("form");
    var hidden = document.createElement("input");
    form.method = "post";
    form.action = "/sample/" + id;
    hidden.type = "hidden";
    hidden.name = "_method"
    hidden.value = "delete";
    form.appendChild(hidden);
    document.body.appendChild(form);
    form.submit();
}

以上、5APIに沿ってControllerとtemplateを実装しました。いくつかの書籍や、フレームワークのプログラムを見ながら進めていますが、実装の意図などからソフトウェアの全体像が少しずつ掴めてきて面白いです。

本記事は動作に必要な部分だけ抜き出していますが、ソースは以下にありますので必要な方はお願いいたします。
github kaikusakari/spring_crud

17
35
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
17
35