0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Spring入門】第8章 社員一覧画面

0
Last updated at Posted at 2026-09-29

いよいよ社員管理アプリの画面を作ります。第7章で作った Repository を使ってデータベースから社員を取り出し、Thymeleaf で一覧表として表示します。

この章で学ぶこと

  • Controller に Repository を注入して、データベースのデータを画面に渡す方法
  • Thymeleaf の th:each で、リストの件数分だけ行を繰り返す方法
  • 画面に表示しやすい形にデータを変換する方法(性別・日付・部署名)
  • CSS などのファイルを置く static フォルダーの役割

8.1 この章で作るもの

この章が終わると、Chrome で http://localhost:8080/employees を開いたときに、次のような社員一覧が表示されるようになります。表示されているのは、第3章でデータベースに登録した3人の社員です。

ch08-list.png
図8-1 この章で完成する社員一覧画面

「新規登録」「変更」「削除」のボタンは、第9章以降で順番に追加していきます。この章では、一覧を表示するところまでを作ります。

この章で作成・変更するファイルは次のとおりです。

ファイル 作業 内容
controller/EmployeeListController.java 新規 社員一覧画面を表示する Controller
static/css/app.css 新規 画面の見た目を整える CSS
templates/employee/list.html 新規 社員一覧画面のテンプレート

ch08-1.png
図8-2 社員一覧画面が表示されるまでの流れ

8.2 EmployeeListController を作る

次に、社員一覧画面を表示する Controller を作ります。

  1. src/main/java → com.example.employeeapp.controller パッケージ(第4章で作成)を右クリックし、新規 → クラス を選びます。
  2. 「名前」に EmployeeListController と入力し、完了 をクリックします。
  3. エディターが開くので、次のように入力して保存します。
src/main/java/com/example/employeeapp/controller/EmployeeListController.java
package com.example.employeeapp.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 com.example.employeeapp.entity.Employee;
import com.example.employeeapp.repository.EmployeeRepository;

@Controller
public class EmployeeListController {

    @Autowired
    private EmployeeRepository employeeRepository;

    /** 社員一覧画面を表示
     * 社員IDの順に社員を取り出して表示
     * @param model 表示する社員情報
     * @return 社員一覧画面 */
    @GetMapping("/employees")
    public String list(Model model) {
        List<Employee> employees = employeeRepository.findAllByOrderByEmpIdAsc();
        model.addAttribute("employees", employees);
        return "employee/list";
    }
}

第5章で予告したとおり、@Autowired で EmployeeRepository を受け取る 形になっています。new を書いていないのに employeeRepository が使えるのは、Spring が第7章で作った EmployeeRepository の実体(Bean)を注入してくれるからです。

【再確認】クラス名は補完で入力する

List や Employee などのクラス名、@GetMapping などのアノテーションは、途中まで打って Ctrl + Space で補完すると、import 文も自動で追加されます(第4章「入力は補完で行う」)。List のように同じ名前のクラスが複数ある場合は、List - java.util を選んでください。

8.3 CSS ファイルを作る

表に罫線を付けるなど、画面の見た目を整えるための CSS ファイルを作ります。CSS ファイルは src/main/resources/static フォルダーの中に置きます。

  1. src/main/resources → static フォルダーを右クリックし、新規 → フォルダー を選びます。
  2. 「フォルダー名」に css と入力し、完了 をクリックします。
  3. 作成した css フォルダーを右クリックし、新規 → ファイル を選びます。
  4. 「ファイル名」に app.css と入力し、完了 をクリックします。
  5. エディターが開くので、次のように入力して保存します。
src/main/resources/static/css/app.css
body { /* ページ全体 */
    margin: 24px;
    color: #222;
}

h1 { /* 見出し */
    font-size: 24px;
}

table { /* 表 */
    border-collapse: collapse;
    margin-bottom: 16px;
}

th, td { /* 表のマス */
    border: 1px solid #999;
    padding: 6px 12px;
    text-align: left;
}

th { /* 表の見出しのマス */
    background-color: #eee;
}

a.button { /* リンクをボタンの見た目にする(新規登録・変更・戻るボタン用) */
    display: inline-block;
    padding: 1px 6px;
    border: 1px solid #767676;
    border-radius: 3px;
    background-color: #efefef;
    color: #000;
    font-size: 13px;
    text-decoration: none;
}

form.inline { /* フォームを横に並べる(削除ボタン用) */
    display: inline;
}

.error { /* 入力チェックのエラーメッセージ */
    color: #c00;
    font-size: 14px;
}

最後の a.button、form.inline、.error は、この章ではまだ使いません。a.button はリンクをボタンの見た目にするため(第10章以降)、form.inline はボタンを横に並べるため(第9章以降)、.error は入力チェックのエラーメッセージを赤く表示するため(第13章以降)に使います。

static フォルダーの役割

static フォルダーに置いたファイルは、Spring Boot が そのまま ブラウザに送ります。CSS や画像、JavaScript のファイルなど、内容が変わらないファイルを置く場所です。

URL は、static フォルダーの中の場所がそのまま使われます。今回作ったファイルは、http://localhost:8080/css/app.css という URL でアクセスできます。

フォルダー 置くもの ブラウザへの送られ方
templates Thymeleaf のテンプレート(HTML) Controller から呼ばれ、データが埋め込まれてから送られる
static CSS、画像、JavaScript など ファイルの中身がそのまま送られる

8.4 一覧画面のテンプレートを作る

Controller の list メソッドは、"employee/list" を返しています。これは templates/employee/list.html を使う、という意味でした(第4章)。まず employee フォルダーを作り、その中にテンプレートを作ります。

  1. src/main/resources → templates フォルダーを右クリックし、新規 → フォルダー を選びます。
  2. 「フォルダー名」に employee と入力し、完了 をクリックします。
  3. 作成した employee フォルダーを右クリックし、新規 → ファイル を選びます。
  4. 「ファイル名」に list.html と入力し、完了 をクリックします。
  5. エディターが開くので、次のように入力して保存します。
src/main/resources/templates/employee/list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>社員一覧</title>
<link rel="stylesheet" th:href="@{/css/app.css}">
</head>
<body>
  <h1>社員一覧</h1>

  <table>
    <tr>
      <th>社員ID</th>
      <th>氏名</th>
      <th>性別</th>
      <th>年齢</th>
      <th>生年月日</th>
      <th>部署</th>
      <th>住所</th>
    </tr>
    <tr th:each="employee : ${employees}">
      <td th:text="${employee.empId}"></td>
      <td th:text="${employee.name}"></td>
      <td th:switch="${employee.gender}">
        <span th:case="1">男</span>
        <span th:case="2">女</span>
      </td>
      <td th:text="${employee.age}"></td>
      <td th:text="${#dates.format(employee.birthDate, 'yyyy/MM/dd')}"></td>
      <td th:text="${employee.department.deptName}"></td>
      <td th:text="${employee.address}"></td>
    </tr>
  </table>
</body>
</html>

【ご注意】フォルダーの場所に注意

list.html は、templates の 中の employee フォルダーに作ってください。templates の直下に作ると、Controller が返す "employee/list" と場所が合わず、エラーになります。

8.5 動作確認

  1. アプリを起動している場合は、コンソールの赤い四角(終了)ボタンで一度停止してから、プロジェクトを右クリック → 実行 → Spring Boot アプリケーション で起動し直します(Boot ダッシュボードの再起動ボタンでもかまいません)。停止している場合は、そのまま起動します。保存しただけでは、動いているアプリには反映されません。
  2. コンソールに Started EmployeeAppApplication と表示されたら、Chrome で http://localhost:8080/employees を開きます。

ch08-list.png
図8-3 社員一覧画面

第3章で登録した3人の社員が、社員IDの順に表示されれば成功です。性別が「男」「女」、生年月日が「2000/06/22」の形式、部署が部署名で表示されていることを確認してください。

【便利な使い方】データベースと見比べてみよう

SQL Developer で第3章の結合 SELECT を実行し、画面に表示された内容と同じであることを確かめてみましょう。アプリはデータベースの内容をそのまま表示しているので、SQL Developer でデータを変更して COMMIT すると、Chrome で画面を再読み込みしたときに一覧にも反映されます。

8.6 解説

Controller の処理

list メソッドがしていることは、次の3つだけです。

  1. employeeRepository.findAllByOrderByEmpIdAsc() で、全社員を社員IDの順に取り出す(第7章で作ったメソッド)
  2. model.addAttribute("employees", employees) で、取り出した社員のリストに employees という名前を付けて Model に入れる
  3. "employee/list" を返して、templates/employee/list.html で画面を作るよう指示する

データベースからデータを取り出す処理は Repository に、画面の見た目はテンプレートに任せ、Controller は「何を取り出して、どの画面に渡すか」だけを決めています。第1章で学んだ MVC の役割分担のとおりです。

Thymeleaf の書き方

書き方 意味
th:each="employee : ${employees}" Model の employees(社員のリスト)から1人ずつ取り出して employee という名前を付け、その要素(ここでは <tr>)を人数分繰り返す。Java の拡張 for 文 for (Employee employee : employees) と同じ考え方
th:text="${employee.name}" タグの中身を、employee の name の値に置き換える
th:switch="${employee.gender}"
th:case="1"
th:switch に書いた値(性別)と同じ th:case の要素だけを表示する。1 なら「男」、2 なら「女」が表示される
${employee.department.deptName} 社員が所属する部署の部署名
${#dates.format(employee.birthDate, 'yyyy/MM/dd')} 日付(Date)を「2000/06/22」の形式の文字に変換する
th:href="@{/css/app.css}" アプリの中の URL を作る。@{…} は URL を表す書き方

${employee.name} はゲッターを呼んでいる

${employee.name} と書くと、Thymeleaf は employee.getName() を呼び出して値を取り出します。フィールドを直接見ているのではなく、「get + 先頭を大文字にした名前」のメソッド を呼んでいます。

テンプレートの書き方 呼び出されるメソッド
${employee.empId} employee.getEmpId()
${employee.gender} employee.getGender()
${employee.department.deptName} employee.getDepartment().getDeptName()

部署名が取れる仕組み

社員テーブルには部署IDしか入っていませんが、画面には部署名が表示されています。これは第6章で、Employee クラスに @ManyToOne を付けた Department 型のフィールドを持たせたからです。

JPA は社員を取り出すときに、部署IDをもとに部署のデータも一緒に取り出し、employee.getDepartment() で使えるようにしてくれます。第3章で SQL Developer から実行した「社員テーブルと部署テーブルの結合」と同じことを、JPA が自動で行っているのです。

8.7 コンソールで SQL を確認する

第4章で application.properties に spring.jpa.show-sql=true を設定したので、JPA が実行した SQL がコンソールに表示されます。Chrome で一覧画面を開いたあと、Eclipse のコンソールを見てみましょう。

コンソール(例)
Hibernate:
    select
        e1_0.emp_id,
        e1_0.address,
        e1_0.age,
        e1_0.birth_date,
        e1_0.dept_id,
        e1_0.gender,
        e1_0.name
    from
        employee e1_0
    order by
        e1_0.emp_id
Hibernate:
    select
        d1_0.dept_id,
        d1_0.dept_name
    from
        department d1_0
    where
        d1_0.dept_id=?
(部署を取り出す select が、社員が所属する部署の数だけ続く)

まず社員テーブル(employee)を社員IDの順に取り出し、続いて部署テーブル(department)から、社員が所属する部署を1件ずつ取り出していることがわかります。表示される SQL の細かい形は、バージョンなどによって変わることがあります。

【知識メモ】SQL を書かなくても SQL は動いている

私たちは SQL を1行も書いていませんが、裏側ではこのように SQL が実行されています。うまく動かないときは、コンソールの SQL を見ると原因がわかることがあります。

【ご注意】現場では

この教材のデータは数件なので問題になりませんが、上のように「社員を取り出したあと、部署を1件ずつ取り出す」動きは、データ量が多い実際のシステムでは SQL の回数が増え、性能に大きく影響することがあります。現場では、どんな SQL が何回実行されているかを確認し、必要に応じてチームで取り出し方を検討するようにしましょう。

8.8 よくあるエラー

症状 原因 対処
500 エラーになり、コンソールに TemplateInputException と表示される Controller が返すテンプレート名と、テンプレートの場所・ファイル名が合っていない return "employee/list"; と、templates/employee/list.html の場所・つづりを確認する
表の見出しだけが表示され、社員が1人も表示されない ${employees} のつづりが、Controller の model.addAttribute("employees", …) の名前と違う Controller とテンプレートで同じ名前になっているか確認する
500 エラーになり、Property or field 'xxx' cannot be found と表示される テンプレートに書いた名前に対応するゲッターがない(例:${employee.gendername} と小文字で書いた) 名前のつづりと大文字・小文字を、Entity のゲッター名と見比べる
表に罫線が付かない(CSS が効いていない) app.css の場所が違う、または th:href のパスが違う src/main/resources/static/css/app.css にあるか、th:href="@{/css/app.css}" と書いたかを確認する。Chrome で http://localhost:8080/css/app.css を開いて中身が表示されるかも確かめる
404 エラー(Whitelabel Error Page)になる URL の打ち間違い、または @GetMapping の URL の間違い Chrome の URL が /employees になっているか、@GetMapping("/employees") と一致しているか確認する

8.9 まとめと確認問題

まとめ

  • Controller は @Autowired で Repository を受け取り、取り出したデータを Model に入れてテンプレートに渡す
  • th:each を使うと、リストの件数分だけ HTML の要素を繰り返せる
  • ${employee.name} は、ゲッター getName() を呼び出して値を取り出す
  • 性別の 1・2 は、th:switch と th:case で「男」「女」に切り替えて表示する
  • @ManyToOne のおかげで、${employee.department.deptName} と書くだけで部署名を表示できる
  • 日付は #dates.format で表示用の形式に変換できる
  • CSS や画像は static フォルダーに置くと、そのままブラウザに送られる

確認問題

問1 Controller の list メソッドが "employee/list" を返すと、どのファイルが画面の作成に使われますか。

解答を見る

src/main/resources/templates/employee/list.html です。templates/ と拡張子 .html は自動で補われます。

問2 th:each="employee : ${employees}" は、Java のどんな書き方に近いですか。

解答を見る

拡張 for 文 for (Employee employee : employees) { … } に近い書き方です。リストから1人ずつ取り出して、要素を人数分繰り返します。

問3 社員テーブルの性別には 1・2 の数値が入っています。一覧画面で「男」「女」と表示するために、テンプレートで何を使いましたか。

解答を見る

th:switch と th:case です。th:switch="${employee.gender}" の値が 1 なら th:case="1" の「男」が、2 なら th:case="2" の「女」が表示されます。

問4 社員テーブルには部署IDしか入っていないのに、一覧画面に部署名を表示できるのはなぜですか。

解答を見る

Employee クラスが @ManyToOne で Department 型のフィールドを持っているため、JPA が部署IDをもとに部署のデータも取り出してくれるからです。テンプレートでは ${employee.department.deptName} と書くだけで部署名を取り出せます。

問5 src/main/resources/static/css/app.css に置いたファイルには、どの URL でアクセスできますか。

解答を見る

http://localhost:8080/css/app.css です。static フォルダーの中の場所が、そのまま URL になります。


前へ

第7章 JPA 入門② Repository

次へ

第9章 社員削除

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?