【Java・SpringBoot】Spring JDBC でユーザー一覧画面（SpringBootアプリケーション実践編11）

ホーム画面からユーザー一覧画面に遷移し、ユーザーの詳細を表示するアプリケーションを作成して
Spring JDBCの使い方について学びます⭐️
今回はユーザーを登録（insert）した結果を確認できるように、**ユーザー一覧画面**を実装します！
構成は前回の記事を参考にしてください

⭐️前回の記事
[【Java・SpringBoot】Spring JDBC（SpringBootアプリケーション実践編9）](https://qiita.com/suema0331/items/23c8c7e9dec01b792a55)
[【Java・SpringBoot】Spring JDBC でユーザー登録（SpringBootアプリケーション実践編10）](https://qiita.com/suema0331/items/f07852225007570916c5)

#リポジトリークラス実装
###queryForObjectメソッドでObjectの取得
* 第１引数に**SQL文**、第２引数に**戻り値のオブジェクトのclass**を指定
    * `int count = jdbc.queryForObject("SELECT COUNT(*) FROM m_user", Integer.class);`


###queryForListメソッドで複数件のselect
* 戻り値の型には`List<Map<String,Object>>`を指定
    * **Listが行、Mapが列**
        * `List<Map<String, Object>> getList = jdbc.queryForList("SELECT * FROM m_user");`
    * **Mapのgetメソッド**でテーブルのカラム名を指定することで値を取得可能
    * 引数を追加すれば、**PreparedStatement**を使える
    * 以下では拡張for文を使って、`List<Map<String,Object>>`を`List<User>`に変換している
        * `for (Map<String, Object> map : getList) {...}`


```UserDaoJdbcImpl.java
package com.example.demo.login.domain.repository.jdbc;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.example.demo.login.domain.model.User;
import com.example.demo.login.domain.repository.UserDao;

@Repository("UserDaoJdbcImpl")
public class UserDaoJdbcImpl implements UserDao {

    @Autowired
    JdbcTemplate jdbc;

    // Userテーブルの件数を取得.
    @Override
    public int count() throws DataAccessException {

        //全件取得してカウント
        int count = jdbc.queryForObject("SELECT COUNT(*) FROM m_user", Integer.class);
        return count;
    }

    // Userテーブルにデータを1件insert.
    @Override
    public int insertOne(User user) throws DataAccessException {

        //１件登録
        int rowNumber = jdbc.update("INSERT INTO m_user(user_id,"
                + " password,"
                + " user_name,"
                + " birthday,"
                + " age,"
                + " marriage,"
                + " role)"
                + " VALUES(?, ?, ?, ?, ?, ?, ?)",
                user.getUserId(),
                user.getPassword(),
                user.getUserName(),
                user.getBirthday(),
                user.getAge(),
                user.isMarriage(),
                user.getRole());

        return rowNumber;
    }

    // Userテーブルのデータを１件取得
    @Override
    public User selectOne(String userId) throws DataAccessException {
        return null;
    }

    // Userテーブルの全データを取得.
    @Override
    public List<User> selectMany() throws DataAccessException {

        // M_USERテーブルのデータを全件取得
        List<Map<String, Object>> getList = jdbc.queryForList("SELECT * FROM m_user");
        // 結果返却用の変数
        List<User> userList = new ArrayList<>();
        // 取得したデータを結果返却用のListに格納していく
        for (Map<String, Object> map : getList) {

            //Userインスタンスの生成
            User user = new User();
            // Userインスタンスに取得したデータをセットする
            user.setUserId((String) map.get("user_id")); //ユーザーID
            user.setPassword((String) map.get("password")); //パスワード
            user.setUserName((String) map.get("user_name")); //ユーザー名
            user.setBirthday((Date) map.get("birthday")); //誕生日
            user.setAge((Integer) map.get("age")); //年齢
            user.setMarriage((Boolean) map.get("marriage")); //結婚ステータス
            user.setRole((String) map.get("role")); //ロール
            //結果返却用のListに追加
            userList.add(user);
        }
        return userList;
    }

    // Userテーブルを１件更新.
    @Override
    public int updateOne(User user) throws DataAccessException {
        return 0;
    }

    // Userテーブルを１件削除.
    @Override
    public int deleteOne(String userId) throws DataAccessException {
        return 0;
    }

    //SQL取得結果をサーバーにCSVで保存する
    @Override
    public void userCsvOut() throws DataAccessException {
    }
}

```

#サービスクラス
* カウントと複数検索用のメソッドを用意

```UserService.java
package com.example.demo.login.domain.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.login.domain.model.User;
import com.example.demo.login.domain.repository.UserDao;

@Service
public class UserService {
    @Autowired
    UserDao dao;

    public boolean insert(User user) {
        // insert実行
        int rowNumber = dao.insertOne(user);
        // 判定用変数
        boolean result = false;

        if (rowNumber > 0) {
            // insert成功
            result = true;
        }
        return result;
    }

    //カウント用メソッド.
    public int count() {
        return dao.count();
    }

    //全件取得用メソッド.
    public List<User> selectMany() {
        // 全件取得
        return dao.selectMany();
    }
}
```
#ホーム画面用のコントローラークラスを修正
* ホーム画面の**ユーザー管理**というリンクをクリックすると、データベースから全ユーザーの情報を取ってくる
* コントローラークラスでは、**カウント結果と複数検索結果をModelクラスに登録**（addAttribute）し、ユーザー一覧画面で、**Modelから値を取得して表示**する

```HomeController.java
package com.example.demo.login.controller;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.example.demo.login.domain.model.User;
import com.example.demo.login.domain.service.UserService;

@Controller
public class HomeController {

    @Autowired
    UserService userService;

    @GetMapping("/home")
    public String getHome(Model model) {

        //コンテンツ部分にユーザー詳細を表示するための文字列を登録
        model.addAttribute("contents", "login/home :: home_contents");
        return "login/homeLayout";
    }

    @GetMapping("/userList")
    public String getUserList(Model model) {

        //コンテンツ部分にユーザー一覧を表示するための文字列を登録
        model.addAttribute("contents", "login/userList :: userList_contents");
        //ユーザー一覧の生成
        List<User> userList = userService.selectMany();
        //Modelにユーザーリストを登録
        model.addAttribute("userList", userList);
        //データ件数を取得
        int count = userService.count();
        model.addAttribute("userListCount", count);
        return "login/homeLayout";
    }
        
    @PostMapping("/logout")
    public String postLogout() {
        //ログイン画面にリダイレクト
        return "redirect:/login";
    }

    @GetMapping("/userList/csv")
    public String getUserListCsv(Model model) {
        return getUserList(model);
    }
}
```

#ユーザー一覧画面を作成
###日付型のフォーマット指定
* **`#dates.format()`メソッド**
    * 第１引数：フォーマットする値
    * 第２引数：フォーマットを指定
        * `<td th:text="${#dates.format(user.birthday, 'YYYY/MM/dd')}"></td>`

###動的URL
* ユーザーを１件取得して表示するには、検索するためのユーザーIDをコントローラークラスに渡す必要がある
* →**`th:href`**の値の中にユーザーIDを入れる
    * `<a class="btn btn-primary" th:href="@{'/userDetail/' + ${user.userId}}">`

```userList.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta charset="UTF-8"></meta>
</head>
<body>
    <!-- コンテンツ部分 -->
    <div th:fragment="userList_contents">
        <div class="page-header">
            <h1>ユーザー一覧</h1>
        </div>
        <table class="table table-bordered table-hover table-striped">
            <tr>
                <th class="info col-sm-2">ユーザID</th>
                <th class="info col-sm-2">ユーザ名</th>
                <th class="info col-sm-2">誕生日</th>
                <th class="info col-sm-2">年齢</th>
                <th class="info col-sm-2">結婚</th>
                <th class="info col-sm-2"></th>
            </tr>
            <tr th:each="user : ${userList}">
                <td th:text="${user.userId}"></td>
                <td th:text="${user.userName}"></td>
                <td th:text="${#dates.format(user.birthday, 'YYYY/MM/dd')}"></td>
                <td th:text="${user.age}"></td>
                <td th:text="${user.marriage} ? '既婚' : '未婚'"></td>
                <td>
                    <!-- ユーザー詳細画面へのリンク(動的URL) -->
                    <a class="btn btn-primary" th:href="@{'/userDetail/' + ${user.userId}}">
                        詳細
                    </a>
                </td>
            </tr>
        </table>
        <!-- ユーザー一覧の件数 -->
        <label th:text=" '合計：' + ${userListCount} + '件' "></label><br/>
        <!-- 更新・削除処理の結果表示用 -->
        <label class="text-info" th:text="${result}">結果表示</label><br/>
        <!-- CSV出力用のリンク -->
        <a class="btn btn-primary" th:href="@{'/userList/csv'}">CSV出力</a>
    </div>
</body>
</html>
```

#SpringBootを起動して画面を確認！
* ログイン後のホーム画面から、ユーザー管理のリンクをクリックすると、ユーザー一覧画面が表示されます
* ユーザー登録画面で登録をすると、この画面で見れるようになりました〜^^

 
![ユーザ管理画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282755/d94cbf99-543c-d309-6643-8f529f2d9077.png)