SpringBootやってみる~DBアクセス(mybatis)編~ データ取得②

#目的
自己学習向け・初心者向けメモ。
前回の [SpringBootやってみる~DBアクセス(mybatis)編~ データ取得①](https://qiita.com/y_ogawa_naaaa/items/26da3b019f090abcfe36 "SpringBootやってみる~DBアクセス(mybatis)編~ データ取得①") のアプリケーションをベースとする

#概要
- [完成図(予定)](#完成図(予定)) 
- [アプリケーションの実装](#アプリケーションの実装) 
- [アプリケーションの実行](#アプリケーションの実行)
- [次回](#次回)

#完成図(予定)
検索画面                 　　　　　　　　　　　　　　　検索結果画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530028/058be6a6-3255-bfa2-19af-6aba0a530bba.png)　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530028/8eb42a50-f4e6-1b79-7882-3f778943f3c6.png)

#アプリケーションの実装
作成したサンプルプログラムの構成は以下の通り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530028/3c12118d-2f50-7be4-09d3-dfd9584e88ce.png)

赤枠で囲っているものは、前回のソースコードから追加・変更したもので本記事にて記載する

まず、Controllerクラスは以下の通り
ページ遷移、検索処理などを記載


```DemoController.java
package com.example.demo.controller;

import java.util.ArrayList;
import java.util.List;

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

import com.example.demo.entity.UserInfo;
import com.example.demo.form.DemoForm;
import com.example.demo.form.SearchForm;
import com.example.demo.service.DemoService;


@Controller
@SessionAttributes(types = {SearchForm.class})
public class DemoController {

    /**
     * Demoサービスクラスへのアクセス
     */
    @Autowired
    private DemoService demoService;

    /**
     * 初期表示(検索)画面に遷移する
     * @return 検索画面へのパス
     */
    @RequestMapping("/")
    public String index(){
        return "search";
    }

    /**
     * 追加処理を行う画面から検索画面に戻る
     * @return 検索画面へのパス
     */
    @RequestMapping(value = "/add", params = "back")
    public String addBack(){
        return "search";
    }

    /**
     * ユーザー情報テーブルのデータを取得して返却する
     * @return ユーザーデータリスト
     */
    @ModelAttribute("demoFormList")
    public List<UserInfo> userDataList(){
        List<UserInfo> demoFormList = new ArrayList<>();
        return demoFormList;
    }

    /**
     * 検索用Formオブジェクトを初期化して返却する
     * @return 検索用Formオブジェクト
     */
    @ModelAttribute("searchForm")
    public SearchForm createSearchForm(){
        SearchForm searchForm = new SearchForm();
        return searchForm;
    }

    /**
     * 検索処理を行い、一覧画面に遷移する
     * @param searchForm 検索用Formオブジェクト
     * @param model Modelオブジェクト
     * @param result バインド結果
     * @return 一覧画面へのパス
     */
    @RequestMapping("/search")
    public String search(SearchForm searchForm, Model model, BindingResult result){
        //検索用Formオブジェクトのチェック処理
        //ユーザー情報リストを取得
        List<DemoForm> demoFormList = demoService.demoFormList(searchForm);
        //ユーザー情報リストを更新
        model.addAttribute("demoFormList", demoFormList);
        return "search_result";
    }
}
```

Formクラスは以下の通り

```DemoForm.java
package com.example.demo.form;

import java.util.LinkedHashMap;
import java.util.Map;

import lombok.Data;

/**
 * Formオブジェクトのクラス
 */
@Data
public class DemoForm {

    /** ID */
    private String id;

    /** 名前 */
    private String name;

    /** 性別 */
    private String sex;
}
```

```SearchForm.java
package com.example.demo.form;

import java.util.LinkedHashMap;
import java.util.Map;

public class SearchForm {

	/** 検索用ＩＤ */
	private String searchId;

	/** 検索用名前 */
	private String searchName;

	/** 検索用性別 */
	private String searchSex;

	public String getSearchId() {
		return searchId;
	}

	public void setSearchId(String searchId) {
		this.searchId = searchId;
	}

	public String getSearchName() {
		return searchName;
	}

	public void setSearchName(String searchName) {
		this.searchName = searchName;
	}

	public String getSearchSex() {
		return searchSex;
	}

	public void setSearchSex(String searchSex) {
		this.searchSex = searchSex;
	}

	/** 性別のMapオブジェクト */
    public Map<String,String> getSexItems(){
    	Map<String, String> sexMap = new LinkedHashMap<String, String>();
    	sexMap.put("男", "男");
    	sexMap.put("女", "女");
    	return sexMap;
    }
}
```

Mapperクラスは以下の通り
検索条件指定により検索する処理を記載

```UserInfoMapper.java
package com.example.demo.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.example.demo.entity.UserInfo;
import com.example.demo.form.SearchForm;

@Mapper
public interface UserInfoMapper {
	List<UserInfo> findBySearchForm(SearchForm searchForm);
}
```

Serviceクラスとその実装クラスは以下の通り
検索処理を呼び出す処理などを記載

```DemoService.java
package com.example.demo.service;

import java.util.List;

import com.example.demo.form.DemoForm;
import com.example.demo.form.SearchForm;

public interface  DemoService {

    /**
     * ユーザーデータリストを取得
     * @param searchForm 検索用Formオブジェクト
     * @return ユーザーデータリスト
     */
    List<DemoForm> demoFormList(SearchForm searchForm);
}
```

```DemoServiceImpl.java
package com.example.demo.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.entity.UserInfo;
import com.example.demo.form.DemoForm;
import com.example.demo.form.SearchForm;
import com.example.demo.mapper.UserInfoMapper;

@Service
public class DemoServiceImpl implements DemoService{

    /**
     * ユーザー情報テーブルへアクセスするマッパー
     */
    @Autowired
    private UserInfoMapper mapper;

    /**
     *
     */
    @Override
    public List<DemoForm> demoFormList(SearchForm searchForm) {
        List<DemoForm> demoFormList = new ArrayList<>();
        //ユーザー情報テーブルから検索条件に合うデータを取得する
        List<UserInfo> userInfoList = mapper.findBySearchForm(searchForm);
        for (UserInfo userInfo : userInfoList) {
            demoFormList.add(getDemoForm(userInfo));
        }
        return demoFormList;
    }

    /**
     * DemoFormオブジェクトに引数のユーザーデータの各値を設定する
     * @param userInfo ユーザー情報
     * @return DemoFormオブジェクト
     */
    private DemoForm getDemoForm(UserInfo userInfo){
        if(userInfo == null){
            return null;
        }
        DemoForm demoForm = new DemoForm();
        demoForm.setId(String.valueOf(userInfo.getId()));
        demoForm.setName(userInfo.getName());
        demoForm.setSex(userInfo.getSex());
        return demoForm;
    }
}
```

Mapperクラスに対応するXMLファイルは以下の通り
findBySearchFormメソッドのSQLを記載

```UserInfoMapper.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.UserInfoMapper">
	<select id="findBySearchForm" parameterType="com.example.demo.form.SearchForm" resultType="com.example.demo.entity.UserInfo">
		SELECT u.id, u.name, u.sex FROM userinfo u
		<if test="(searchId != null and searchId != '') or (searchName != null and searchName != '') or (searchSex != null and searchSex != '')">
			WHERE
		</if>
		<if test="searchId != null and searchId != ''">
			u.id = #{searchId}
		</if>
		<if test="searchName != null and searchName != ''">
            <if test="searchId == null or searchId == ''">
				u.name like '%${searchName}%'
			</if>
			<if test="searchId != null and searchId != ''">
				AND u.name like '%${searchName}%'
			</if>
		</if>
		<if test="searchSex != null and searchSex != ''">
            <if test="(searchId == null or searchId == '') and (searchName == null or searchName == '')">
				u.sex = #{searchSex}
			</if>
			<if test="(searchId != null and searchId != '') or (searchName != null and searchName != '')">
				AND u.sex = #{searchSex}
			</if>
		</if>
        ORDER BY u.id
    </select>
</mapper>
```

HTMLは以下の通り
・search.html：検索画面
・search_result.html：検索結果画面

```search.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>検索画面</title>
</head>
<body>
	<form method="post" action="/search" th:object="${searchForm}">
		<table border="1">
			<tr>
				<th>ＩＤ</th>
				<td><input type="text" th:value="*{searchId}" th:field="*{searchId}" /></td>
			</tr>
			<tr>
				<th>名前</th>
				<td><input type="text" th:value="*{searchName}" th:field="*{searchName}" /></td>
			</tr>
			<tr>
				<th>性別</th>
				<td>
					<select th:field="*{searchSex}">
					<option value=""></option>
						<option th:each="item : *{getSexItems()}" th:value="${item.key}" th:text="${item.value}"/>
					</select>
				</td>
			</tr>
		</table>
		<br/><br/>
		<input type="submit" value="検索" /><br/><br/>
	</form>
</body>
</html>
```

```search_result.html
<!DOCTYPE html>
<html lang="jp" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>検索結果</title>
</head>
<body>
    <table border="1">
        <tr>
            <th>ID</th>
            <th>名前</th>
            <th>性別</th>
        </tr>
        <tr th:each="obj : ${demoFormList}">
            <td th:text="${obj.id}"></td>
            <td th:text="${obj.name}"></td>
            <td th:text="${obj.sex}"></td>
        </tr>
    </table>
    <br/><br/>
    <form method="post" action="/add">
        <input type="submit" name="back" value="戻る" />
    </form>
</body>
</html>
```

#アプリケーションの実行
Spring Boot App で起動して http://localhost:8080 にアクセスするとこのような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530028/b8b74bad-45af-9a48-b1b5-b604ae4b973a.png)

検索条件を入力して実行すると・・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530028/bb48c79e-bca8-cb93-aeb8-6583a75947e5.png)


こんな感じに
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530028/84e3e8c2-0e9f-ab01-4de3-6d6710c62875.png)


#次回
[SpringBootやってみる~DBアクセス(mybatis)編~ データ登録①](https://qiita.com/y_ogawa_naaaa/items/e6c914dde066c6c9b4df "SpringBootやってみる~DBアクセス(mybatis)編~ データ登録①")