前提
以下記事をもとにプロジェクトの設定を行う
【SpringBoot】プロジェクトの設定 - アルパカノフン
1.画面を作成
index.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="/css/bootstrap.min.css" rel="stylesheet"> <title>メンバー一覧</title> </head> <body> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="/members">メンバー管理</a> </div> </div> </nav> <div class="container"> <div class="card card-primary mb-3"> <div class="card-header"> <h5 class="card-title">メンバーリスト<a href="/members/new" class="btn btn-success float-right">新規</a></h5> </div> <div class="card-body" th:if="!${members.size()}"> <p>メンバーがいません。</p> </div> <table class="table table-striped" th:if="${members.size()}"> <thead> <tr> <th style="width: 10%">ID</th> <th style="width: 30%">名前</th> <th style="width: 10%">年齢</th> <th style="width: 50%"></th> </tr> </thead> <tbody> <tr th:each="member:${members}" th:object="${member}"> <td th:text="*{id}"></td> <td th:text="*{name}"></td> <td th:text="*{age}"></td> <td class="float-right"> <form th:action="@{/members/{id}(id=*{id})}" th:method="delete"> <a class="btn btn-primary" th:href="@{/members/{id}(id=*{id})}">詳細</a> <a class="btn btn-primary" th:href="@{/members/{id}/edit(id=*{id})}">変更</a> <button class="btn btn-primary">削除</button> </form> </td> </tr> </tbody> </table> </div> </div> <script src="/js/jquery-3.5.1.min"></script> <script src="/js/bootstrap.min.js"></script> </body> </html>
new.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="/css/bootstrap.min.css" rel="stylesheet"> <title>メンバー新規</title> </head> <body> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="/members">メンバー管理</a> </div> </div> </nav> <div class="container"> <div class="card card-primary mb-3"> <div class="card-header"> <h5 class="card-title">メンバー新規</h5> </div> <div class="card-body"> <form th:method="post" th:action="@{/members}" th:object="${member}"> <div class="form-group row"> <label class="col-md-2 control-label">名前</label> <div class="col-md-10"> <input class="form-control" type="text" name="name" th:value="*{name}" /> <div class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div> </div> </div> <div class="form-group row"> <label class="col-md-2 control-label">年齢</label> <div class="col-md-10"> <input class="form-control" type="text" name="age" th:value="*{age}"/> <div class="text-danger" th:if="${#fields.hasErrors('age')}" th:errors="*{age}"></div> </div> </div> <div class="form-group row"> <div class="offset-md-2 col-md-10"> <button class="btn btn-primary">新規</button> </div> </div> </form> </div> </div> </div> <script src="/js/jquery-3.5.1.min"></script> <script src="/js/bootstrap.min.js"></script> </body> </html>
show.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="/css/bootstrap.min.css" rel="stylesheet"> <title>メンバー詳細</title> </head> <body> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="/members">メンバー管理</a> </div> </div> </nav> <div class="container"> <div class="card card-primary mb-3"> <div class="card-header"> <h5 class="card-title">メンバー詳細</h5> </div> <div class="card-body"> <div th:object="${member}"> <div class="form-group row"> <label class="col-md-2">氏名</label> <div class="col-md-10" th:text="*{name}"></div> </div> <div class="form-group row"> <label class="col-md-2 control-label">年齢</label> <div class="col-md-10 form-control-static" th:text="*{age}"></div> </div> </div> </div> </div> </div> <script src="/js/jquery-3.5.1.min"></script> <script src="/js/bootstrap.min.js"></script> </body> </html>
edit.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="/css/bootstrap.min.css" rel="stylesheet"> <title>メンバー情報変更</title> </head> <body> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="/members">メンバー管理</a> </div> </div> </nav> <div class="container"> <div class="card card-primary mb-3"> <div class="card-header"> <h5 class="card-title">メンバー詳細</h5> </div> <div class="card-body"> <form th:action="@{/members/{id}(id=*{id})}" th:method="put" th:object="${member}"> <div class="form-group row"> <label class="col-md-2 control-label">名前</label> <div class="col-md-10"> <input class="form-control" type="text" th:field="*{name}" /> <div class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div> </div> </div> <div class="form-group row"> <label class="col-md-2 control-label">年齢</label> <div class="col-md-10"> <input class="form-control" type="text" th:field="*{age}" /> <div class="text-danger" th:if="${#fields.hasErrors('age')}" th:errors="*{age}"></div> </div> </div> <div class="form-group row"> <div class="offset-md-2 col-md-9"> <button class="btn btn-primary">更新</button> </div> </div> </div> </form> </div> </div> <script src="/js/jquery-3.5.1.min"></script> <script src="/js/bootstrap.min.js"></script> </body> </html>
2.Entityを作成
Entityとはテーブルのデータを格納するオブジェクト用のクラス
ファイル名はDBのテーブル名に合わせること
項目名はDBの項目名に合わせること
※Lombokを使用
package com.example.demo.domain; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; import lombok.Data; @Data public class Member { private long id; @NotBlank private String name; @Pattern(regexp="[0-9]+") private String age; }
3.Mybatis
インターフェースを作成
テーブルにアクセスするメソッドを記載する
package com.example.demo.mapper; import java.util.List; import org.apache.ibatis.annotations.Mapper; import com.example.demo.domain.Member; @Mapper public interface MemberMapper { List<Member> selectAll(); }
SQLを記載するXMLを作成
※要注意※パッケージ名(階層も)とファイル名はインタフェースと合わせること
namespase=インタフェースのパスを指定
resultType=Entityクラスのパスを指定
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.mapper.MemberMapper"> <select id="findAll" resultType="com.example.demo.domain.Member"> select * from member </select> <select id="findOne" resultType="com.example.demo.domain.Member"> select * from member where id= #{id} </select> <insert id="save" useGeneratedKeys="true" keyProperty="id"> insert into member(name, age) values(#{name}, #{age}) </insert> <update id="update"> update member set name=#{name}, age=#{age} where id= #{id} </update> <delete id="delete"> delete from member where id = #{id} </delete> </mapper>
4.サービスを作成
package com.example.demo.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.example.demo.domain.Member; import com.example.demo.mapper.MemberMapper; @Service public class MemberService { @Autowired private MemberMapper MemberMapper; @Transactional public List<Member> findAll() { return MemberMapper.findAll(); } @Transactional public Member findOne(Long id) { return MemberMapper.findOne(id); } @Transactional public void save(Member Member) { MemberMapper.save(Member); } @Transactional public void update(Member Member) { MemberMapper.update(Member); } @Transactional public void delete(Long id) { MemberMapper.delete(id); } }
5.コントローラを作成
IndexController
package com.example.demo.web; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import com.example.demo.service.MemberService; @Controller @RequestMapping("/members") public class IndexController { @Autowired private MemberService memberService; // ボタン押下処理 @GetMapping public String index(Model model) { model.addAttribute("members", memberService.findAll()); return "index"; } // 詳細ボタン押下処理 @GetMapping("{id}") public String show(@PathVariable Long id, Model model) { model.addAttribute("member", memberService.findOne(id)); return "show"; } // 削除ボタン押下処理 @DeleteMapping("{id}") public String delete(@PathVariable Long id) { memberService.delete(id); return "redirect:/members"; } }
NewController
package com.example.demo.web; 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.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import com.example.demo.domain.Member; import com.example.demo.service.MemberService; @Controller @RequestMapping("members") public class NewController { @Autowired private MemberService memberService; @GetMapping("new") public String newItem(Member member, Model model) { return "new"; } @ModelAttribute Member setMember() { return new Member(); } @PostMapping public String create(@Validated Member member, BindingResult result, Model model) { if (result.hasErrors()) { return "new"; } else { memberService.save(member); return "redirect:/members"; } } }
EditController
package com.example.demo.web; 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.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import com.example.demo.domain.Member; import com.example.demo.service.MemberService; @Controller @RequestMapping("/members") public class EditController { @Autowired private MemberService memberService; @GetMapping("{id}/edit") public String edit(@PathVariable Long id, @ModelAttribute("member") Member member, Model model) { model.addAttribute("member", memberService.findOne(id)); return "edit"; } @PutMapping("{id}") public String update(@PathVariable Long id, @ModelAttribute("member") @Validated Member member, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("member", member); return "edit"; } else { member.setId(id); memberService.update(member); return "redirect:/members"; } } }