EclipseによるSpringBoot⑥MyBatis update

EclipesによるSpringBootの連載の続きです。
①コントローラ
②Thymeleaf
③MyBatis select
④Validation
⑤MyBatis insert
⑥MyBatis update(今回)

今回のテーマは、MyBatisのupdateです。
updateは、SQL文で更新の命令です。
既存のデータを更新するときに使います。

新規/修正のJavaソース資源のディレクトリ構成を示します。

新規/修正のリソース資源のディレクトリ構成を示します。

修正/新規資源一覧を以下に示します。

#ファイル名概要種別修正/新規
1AddressModiyController.java住所修正コントローラクラスJava新規
2AddressMapper.java住所マッパーインターフェイスJava修正
3AddressService.java住所サービスクラスJava修正
4AddressMapper.xml住所マッパーSQLSQL修正
5PostAction.jsポストアクションJavaScriptJavaScript新規
6List.html住所一覧画面タイムリーフThymeleaf修正
7Modify.html編集画面タイムリーフThymeleaf新規
8ModifyConfirm.html編集確認画面タイムリーフThymeleaf新規
9ModifyComplete.html編集完了画面タイムリーフThymeleaf新規
作成手順 ①ソースの作成
 ①-1住所編集コントローラクラス
   編集リンク押下時のメソッド
 ①-2住所編集コントローラクラス
   編集確認画面用のメソッド
 ①-3住所編集コントローラクラス
   更新ボタン押下時のメソッド
 ①-4住所マッパーインターフェイス
   IDをキーとして住所取得メソッド
 ①-5住所マッパーインターフェイス
   住所テーブル更新メソッド
 ①-6住所サービスクラス
   IDをキーとして住所取得メソッド
 ①-7住所サービスクラス
   住所テーブル更新メソッド
②SQL作成
 ②-1IDをキーとして住所取得SQL
 ②-2住所テーブル更新SQL
③JavaScript作成
 ポストアクションJavaScript
④タイムリーフ作成
 ④-1住所一覧画面タイムリーフ
   編集リンクの追加
 ④-2編集画面タイムリーフ
 ④-3編集確認画面タイムリーフ
 ④-4編集完了画面タイムリーフ
①ソースの作成
 ①-1住所編集コントローラクラス
   編集リンク押下時のメソッド
行数説明
19@RestControllerは、受付用のコントローラクラスのアノテーションになります。
20public class AddressModifyControlerは、住所編集コントローラクラスの定義になります。
21~22@Aurowiredは、自動でインスタンスを行うアノテーションになります。
住所サービスクラスのインスタンスを行います。
24@RequestMapping("/modify")は、Get/Post両方受付可能なアノテーションになります。
パスは"/modify"を指定します。
25編集リンク押下時に呼び出される編集メソッド(modify)になります。
@RequestParam("modifyId")は、リクエストパラメータのアノテーションになります。
27アドレスサービスクラスの住所取得メソッドを、引数をIDとして、呼び出しています。
29入力フォームクラス(inputForm)のインスタンスを行っています。
30~47アドレステーブルから取得した住所情報を入力フォームクラス(inputForm)設定しています。
nullチェックをしてnullでなければ格納しています。
行数説明
48~51性別マップのインスタンスを行っています。
0:男、1:女の表示を設定していて、入力フォームクラス(inputForm)に設定しています。
54入力フォームクラス(inputForm)をタイムリーフに設定しています。
55編集ID(modifyId)をタイムリーフに設定しています。
56タイムリーフ名をModify(編集画面)に設定しています。

①-2住所編集コントローラクラス
   編集確認画面用のメソッド
行数説明
63@RequestMapping("/modify")は、Get/Post両方受付可能なアノテーションになります。パスは"/modify/confirm"を指定します。
64~67メソッド:modifyConfirm(編集確認画面)
①引数:@Validated @ModelAttribute InuputForm inputForm(バリデーションチェックを実施する)
②引数:BindingResult resutlt(バリデーションチェックの結果が格納される)
③引数:ModelAndView model(遷移先画面連携用のオブジェクト)
④引数:@RequestParam("id") string id(「戻る」/「次へ」ボタン判別用の変数)
⑤引数:@RequestParam("modifyId") long modifyId(編集ID)
69~72戻るボタン押下時(id="back")の処理になります。リダイレクトで住所一覧画面に遷移します。
リダイレクトは、コントローラクラスのリストメソッド実行後に、住所一覧画面に遷移を意味します。
74~84エラー判定時の処理になります。
性別マップのインスタンスと0:男、1:女の表示を設定していて、入力フォームクラス(inputForm)に設定しています。
入力フォームクラス(inputForm)を移先画面連携用のオブジェクトに設定しています。
Modify(編集画面)に遷移先を設定しています。
85編集ID(modifyId)を移先画面連携用のオブジェクトに設定しています。
86modifyConfirm(編集確認画面)に遷移先を設定しています。

①-3住所編集コントローラクラス
   更新ボタン押下時のメソッド
行数説明
90@RequestMapping("/update")は、Get/Post両方受付可能なアノテーションになります。パスは"/update"を指定します。
91~99メソッド:update
①引数:ModelAndView model(遷移先画面連携用のオブジェクト)
②引数:@RequestParam("modifyId") long modifyId(編集ID)
③引数:@RequestParam("name") String name(名前)
④引数:@RequestParam("address") String address(住所)
⑤引数:@RequestParam("mail") String mail(メールアドレス)
⑥引数:@RequestParam("gender") String gender(性別)
⑦引数:@RequestParam("id") String id(「戻る」/「次へ」ボタン判別用の変数)
102~117戻るボタン押下時の処理になります。
入力フォームクラス(inputForm)のインスタンスを生成しています。
名前(name)、住所(address)、メール(mail)、電話番号(tel)、仕事(job)、性別(gender)を入力フォームに設定しています。
性別マップのインスタンスと0:男、1:女の表示を設定していて、入力フォームクラス(inputForm)に設定しています。
入力フォームクラス(inputForm)を遷移先画面連携用のオブジェクトに設定しています。
Modify(編集画面)に遷移先を設定しています。
行数説明
119住所DTOのインスタンスを生成しています。
122~128編集ID(modifyId)、名前(name)、住所(address)、メール(mail)、電話番号(tel)、仕事(job)、性別(gender)を住所DTOに設定しています。
131アドレスサービスクラスの更新メソッドを住所DTOを引数として呼び出しています。
133編集完了画面に遷移先を設定しています。

①-4住所マッパーインターフェイス
   IDをキーとして住所取得メソッド
①-5住所マッパーインターフェイス
   住所テーブル更新メソッド
行数説明
17住所情報取得(selectAddressById)メソッドのIF定義になります。
引数のIDをキーとして、住所情報を取得します。
19住所情報更新(updateAddressById)メソッドのIF定義になります。
引数の住所DTOで、更新します。

①-6住所サービスクラス
   IDをキーとして住所取得メソッド
①-7住所サービスクラス
   住所テーブル更新メソッド

行数説明
32~34メソッド:getAddressById(IDをキーとして住所取得)
引数:long id(long型 ID)
戻り値:AddressDto(住所DTO)
住所マッパーインターフェイスのIDをキーとして住所取得メソッドを呼び出しています。
36~39メソッド:updateAddressById(住所更新)
引数:AddressDto addressDto (住所DTO)
戻り値:void(なし)
住所更新(updateAddressById)メソッド
アドレスマッパーの住所更新メソッドを呼び出しています。

②SQL作成
 ②-1IDをキーとして住所取得SQL
 ②-2住所テーブル更新SQL
行数説明
27~34id(メソッド):selectSddressById
引数:long #{id}
戻り値:AddressDto
(select句)列:*(アスター)すべての列
(from句)テーブル:Address(住所)
(where句)条件:id=#{id}
36~48id(メソッド):updateAddressById
引数:AddressDto
戻り値:なし
(update句)テーブル:Address(住所)
(set句)設定カラム:名前、住所、電話番号、メール、職業、性別
(where句)条件:id=#{id}

③JavaScript作成
 ポストアクションJavaScript
行数説明
4関数:ポストアクション(postAction)
①引数 id:編集ID
②引数 action:送信宛先パス
6住所リストフォーム(document.addressListForm)をformタグ(f)に設定。
7formタグの(f)のメソッドをpostに設定。
8formタグ(f)のアクションに引数のアクション(送信先パス)を設定。
11formタグ(f)modifyIdの値に引数の編集idを設定。
12formタグ(f)を送信する。

④タイムリーフ作成
 ④-1住所一覧画面タイムリーフ
   編集リンクの追加
行数説明
6JavaScriptのPostAction.jsを参照設定しています。
20アドレス一覧画面に編集列を追加しています。
行数説明
35~40<td></td>はテーブルのセルを表すタグです。
<a href></a>はリンクのタグです。
th:attrはタイムリーフのタグで、リンク時の処理になります。
JavaScriptのpostAction関数を、引数リストNoと引数送信パス@{/modify}で、呼び出します。
th:textもタイムリーフのタグで、リストの名前を表示します。
45input type="hidden"は隠し項目用タグになります。編集IDをサーバに送信するために使います。

④-2編集画面タイムリーフ

行数説明
8バリデーションチェックでエラーがある場合は、エラー表示します。
10formタグ 
th:actionは、タイムリーフ用のタグで送信宛先を@{/modify/confirm}に設定。
th:objectは、タイムリーフ用のタグでinputFormクラスと紐づけを行っています。
メソッドをpostに設定しています。
12~37名前、住所、電話番号、メールアドレス、職業、性別の編集用のテキストボックスを表示します。
バリデーションチェックでエラーの場合は、エラーメッセージを表示します。
行数説明
38送信ボタン名を「戻る」に設定しています。
idにbackを設定しています。
39送信ボタン名を「次へ」に設定しています。
idにnextを設定しています。
41input type="hidden"は隠し項目用タグになります。編集IDをサーバに送信するために使います。

④-3編集確認画面タイムリーフ

行数説明
8formタグ 
th:actionは、タイムリーフ用のタグで送信宛先を@{/update}に設定。
th:objectは、タイムリーフ用のタグでinputFormクラスと紐づけを行っています。
メソッドをpostに設定しています。
9~30<table></table>テーブルタグ
<tr></tr>行タグ
<th></th>ヘッダセルタグ
<td></td>セルタグ
th:textは、タイムリーフのタグで表示用に使います。
行数説明
31送信ボタン名を「戻る」に設定しています。
idにbackを設定しています。
32送信ボタン名を「更新」に設定しています。
idにmodifyを設定しています。
34~40input type="hidden"は隠し項目になります。
名前、住所、電話番号、メール、職業、性別、編集IDをサーバに送信用に使用します。

 ④-4編集完了画面タイムリーフ

行数説明
8formタグ 
th:actionは、タイムリーフ用のタグで送信宛先を@{/list}に設定。
メソッドをpostに設定しています。
11送信ボタン名を「一覧へ」に設定しています。
idにnextを設定しています。

これでやっと、準備が整いました。
H2データベースを起動させて、Bootダッシュボードから起動しましょう。
URLをLocalhost:8080/listと打ち込みましょう。
編集列が表示されます。テストE 花子さんをクリックしてみましょう。
職業を「学生→社会人」に編集してみましょう。
「次へ」ボタンを押下します。
編集確認画面で、職業が「学生→社会人」に変更しています。
「更新」ボタンを押下します。
更新完了画面が表示します。
「一覧へ」ボタンを押下します。
住所一覧画面に遷移します。
テストE 花子さんの職業が「学生→社会人」に更新されています。
こうなれば、成功です。本当にお疲れ様です!

☆まとめ☆ 今回は、SQL文の更新のupdateの命令を学びました。
タイムリーフのリンクからsubmit送信する場合は、JavaScriptから
submitする方法について学びました。

■ソースコードのコピーペースト用に記載します。

#1 AddressModifyController.java

package com.example.demo.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.example.demo.dto.AddressDto;
import com.example.demo.form.InputForm;
import com.example.demo.service.AddressService;

@RestController
public class AddressModifyController {
  @Autowired
  private AddressService addressService;

  @RequestMapping("/modify")
  public ModelAndView modify(ModelAndView model, @RequestParam("modifyId")long modifyId) {
    
    AddressDto addressDto = addressService.getAddressById(modifyId);
    
    InputForm inputForm = new InputForm();
    if(addressDto.getName() != null) {
      inputForm.setName(addressDto.getName().trim());
    }
    if(addressDto.getAddress().trim() != null) {
      inputForm.setAddress(addressDto.getAddress().trim());
    }
    if(addressDto.getTel() != null) {
      inputForm.setTel(addressDto.getTel().trim());
    }
    if(addressDto.getMail() != null) {
      inputForm.setMail(addressDto.getMail().trim());
    }
    if(addressDto.getJob() != null) {
      inputForm.setJob(addressDto.getJob().trim());
    }
    if(addressDto.getGender() != null) {
      inputForm.setGender(addressDto.getGender().trim());
    }
    Map genderMap = new HashMap<>();
    genderMap.put("0", "男");
    genderMap.put("1", "女");
    inputForm.setGenderItem(genderMap);
    
    //Thymeleafに住所編集情報を設定
    model.addObject("inputForm",inputForm);
    model.addObject("modifyId",modifyId);
    //Thymeleaf名を設定
    model.setViewName("Modify");
    
    return model;
  }

  //編集確認画面
  @RequestMapping("/modify/confirm")
  public ModelAndView modifyConfirm(@Validated @ModelAttribute InputForm inputForm,
      BindingResult result, ModelAndView model,
      @RequestParam("id")String id,
      @RequestParam("modifyId")long modifyId) {
    //リダイレクトにより一覧画面に戻る
    if(id.equals("back")) {
      model.setViewName("redirect:/List");
      return model;
    }
    //エラーチェック
    if(result.hasErrors()) {
      model.addObject("validationError", "不正な値が入力されました。");
      
      Map genderMap = new HashMap<>();
      genderMap.put("0", "男");
      genderMap.put("1", "女");
      inputForm.setGenderItem(genderMap);
      model.addObject("inputForm",inputForm);
      model.setViewName("Modify");
     return model;
    }
    model.addObject("modifyId",modifyId);
    model.setViewName("ModifyConfirm");
    return model;
  }
  //更新ボタン押下時
  @RequestMapping("/update")
  public ModelAndView update(ModelAndView model,
      @RequestParam("modifyId")long modifyId,
      @RequestParam("name")String name,
      @RequestParam("address")String address,
      @RequestParam("mail")String mail,
      @RequestParam("tel")String tel,
      @RequestParam("job")String job,
      @RequestParam("gender")String gender,
      @RequestParam("id")String id) {
      
    //戻るボタン押下時
    if(id.equals("back")) {
      InputForm inputForm = new InputForm();
      inputForm.setName(name);
      inputForm.setAddress(address);
      inputForm.setMail(mail);
      inputForm.setTel(tel);
      inputForm.setJob(job);
      inputForm.setGender(gender);
      Map genderMap = new HashMap<>();
      genderMap.put("0", "男");
      genderMap.put("1", "女");
      inputForm.setGenderItem(genderMap);
      model.addObject("inputForm",inputForm);
      model.setViewName("Modify");
      return model;
    }
          
    AddressDto addressDto = new AddressDto();
      
    //アドレス情報の設定
    addressDto.setId(modifyId);
    addressDto.setName(name);
    addressDto.setAddress(address);
    addressDto.setMail(mail);
    addressDto.setTel(tel);
    addressDto.setJob(job);
    addressDto.setGender(gender);
      
    //アドレス情報の更新
    addressService.updateAddressById(addressDto);
    //編集完了画面に遷移
    model.setViewName("ModifyComplete");
    return model;
  }
}

#2 AddressMapper.java

package com.example.demo.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.example.demo.dto.AddressDto;

@Mapper
public interface AddressMapper {
  public List selectAddress();

  public long selectIdMax();

  public void insertAddress(AddressDto addressDto);
  
  public AddressDto selectAddressById(long id);
  
  public void updateAddressById(AddressDto addressDto);

}

#3 AddressService.java

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.dto.AddressDto;
import com.example.demo.mapper.AddressMapper;

@Service
public class AddressService {
  @Autowired
  private AddressMapper addressMapper;
  
  //住所一覧取得
  public List getAddress(){
    return addressMapper.selectAddress();
  }
  
  //ID最大値取得
  public long getIdMax() {
    return addressMapper.selectIdMax();
  }
  
  //住所登録
  public void registerAddress(AddressDto addressDto) {
    addressMapper.insertAddress(addressDto);
  }

  //IDをキーとして住所取得
  public AddressDto getAddressById(long id) {
    return addressMapper.selectAddressById(id);
  }

  //住所更新
  public void updateAddressById(AddressDto addressDto) {
    addressMapper.updateAddressById(addressDto);
  }
  
}

#4 AddressMapper.xml

<?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.AddressMapper">
  <select id="selectAddress" resultType="com.example.demo.dto.AddressDto">
    select
      *
    from
      ADDRESS
    order by id
  </select>

  <select id="selectIdMax" resultType="long">
    select
      max(id)
    from
      Address
  </select>
  
  <insert id="insertAddress" parameterType="com.example.demo.dto.AddressDto">
    insert into Address
      (id, address, tel, name, mail, job, gender)
    values(#{id}, #{address}, #{tel}, #{name}, #{mail}, #{job}, #{gender})
  </insert>

  <select id="selectAddressById" parameterType="long" resultType="com.example.demo.dto.AddressDto">
    select
      *
    from
      Address
    where
  id = #{id}
  </select>

  <update id="updateAddressById" parameterType="com.example.demo.dto.AddressDto">
    update
      Address
    set
      name = #{name},
      address = #{address},
      tel = #{tel},
      mail = #{mail},
      job = #{job},
      gender = #{gender}
    where
      id = #{id}
  </update>

</mapper>

#5 PostAction.js

/**
* 編集リンク押下時
*/
function postAction(id, action){
  
  var f=document.addressListForm;
  f.method="post";
  f.action=action;
  f.modifyId.value=id;
  f.submit();
}

#6 List.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>アドレス一覧画面</title>
<script th:src="@{/js/PostAction.js}"></script>
</head>
<body>
  <form id="addressListForm" name="addressListForm" action="#" th:action="@{/input}" method="post">
    <table>
      <tr>
        <th>No</th>
        <th>名前</th>
        <th>住所</th>
        <th>電話番号</th>
        <th>メールアドレス</th>
        <th>職業</th>
        <th>性別</th>
        <th>編集</th>
      </tr>
      <th:block th:each="li:${list}">
        <tr>
          <td th:text="${li.no}"></td>
          <td th:text="${li.name}"></td>
          <td th:text="${li.address}"></td>
          <td th:text="${li.tel}"></td>
          <td th:text="${li.mail}"></td>
          <td th:text="${li.job}"></td>
          <td>
            <span th:if="${li.gender != null}">
              <span th:if="${li.gender == '0'}">男</span>
              <span th:if="${li.gender == '1'}">女</span>
            </span>
          </td>  
          <td>
            <a href="#"
              th:attr="onclick='postAction(\'' +${li.no} + '\',\'' + @{/modify} + '\');'">
              <span th:text="${li.name}"></span>
            </a>
          </td>
        </tr>
      </th:block>
    </table>
    <button type="submit" name="id" th:value="new">新規作成</button>
     <input type="hidden" name="modifyId" >
  </form >
</body>
</html>

#7 Modify.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>編集画面</title>
</head>
<body>
  <p th:if="${validationError}" th:text="${validationError}">validation error</p>

  <form action="#" th:action="@{/modify/confirm}" th:object="${inputForm}" method="post">
    <div>
      <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" >error!</span>
      <p>名前*</p>
      <p><input type="text" id="name" th:field="*{name}"></p>

      <span th:if="${#fields.hasErrors('address')}" th:errors="*{address}" >error!</span>
      <p>住所*</p>
      <p><input type="text" id="address" th:field="*{address}"></p>

      <span th:if="${#fields.hasErrors('tel')}" th:errors="*{tel}" >error!</span>
      <p>電話番号*</p>
      <p><input type="text" id="tel" th:field="*{tel}"></p>

      <span th:if="${#fields.hasErrors('mail')}" th:errors="*{mail}" >error!</span>
      <p>メールアドレス</p>
      <p><input type="text" id="mail" th:field="*{mail}"></p>

      <span th:if="${#fields.hasErrors('job')}" th:errors="*{job}" >error!</span>
      <p>職業</p>
      <p><input type="text" id="job" th:field="*{job}"></p>

      <p>性別</p>
      <p>
        <div th:each="item:*{genderItem}">
          <input type="radio" th:value="${item.key}" th:text="${item.value}" th:field="*{gender}"/>
        </div>
       </p>
      <button type="submit" name="id" th:value="back">戻る</button>
      <button type="submit" name="id" th:value="next">次へ</button>
    </div>
    <input type="hidden" name="modifyId" th:value="${modifyId}" >
  </form>
</body>
</html>

#8 ModifyConfirm.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>編集確認画面</title>
</head>
<body>
  <form action="#" th:action="@{/update}" th:object="${inputForm}" method="post">
    <table>
    <tr>
      <th>名前</th>
      <th>住所</th>
      <th>電話番号</th>
      <th>メールアドレス</th>
      <th>職業</th>
      <th>性別</th>
    </tr>
    <tr>
      <td th:text="*{name}"></td>
      <td th:text="*{address}"></td>
      <td th:text="*{tel}"></td>
      <td th:text="*{mail}"></td>
      <td th:text="*{job}"></td>
      <td>
        <span th:if="*{gender == '0'}">男</span>
        <span th:if="*{gender == '1'}">女</span>
      </td>
    </tr>

    </table>
    <button type="submit" name="id" th:value="back">戻る</button>
    <button type="submit" name="id" th:value="modify">更新</button>

    <input type="hidden" name="name" th:value="*{name}">
    <input type="hidden" name="address" th:value="*{address}">
    <input type="hidden" name="tel" th:value="*{tel}">
    <input type="hidden" name="mail" th:value="*{mail}">
    <input type="hidden" name="job" th:value="*{job}">
    <input type="hidden" name="gender" th:value="*{gender}">
    <input type="hidden" name="modifyId" th:value="${modifyId}" >
  </form>
</body>
</html>

#9 ModifyComplete.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>更新完了画面</title>
</head>
<body>
  <form action="#" th:action="@{/list}" method="post">
    <div>
      <p>更新が完了しました。</p>
      <button type="submit" name="id" th:value="next">一覧へ</button>
    </div>
  </form>
</body>
</html>

Follow me!