【第十回】Spring Frameworkを使ってみる ~データベースにアクセスする④~


前回の第九回ではデータベースに接続し絞込みを行いログイン処理を実装しました。
今回は、テーブルの結合をしてデータを取得していきます。

Spring Framework連載記事 目次

【第一回】Spring Frameworkを使ってみる ~Spring Framework概要と準備~
【第二回】Spring Frameworkを使ってみる ~プロジェクト作成からビルドまで~
【第三回】Spring Frameworkを使ってみる ~サーバで実行~
【第四回】Spring Frameworkを使ってみる ~画面遷移~
【第五回】Spring Frameworkを使ってみる ~データ受け渡し~
【第六回】Spring Frameworkを使ってみる ~入力値チェック~
【第七回】Spring Frameworkを使ってみる ~データベースにアクセスする①~
【第八回】Spring Frameworkを使ってみる ~データベースにアクセスする②~
【第九回】Spring Frameworkを使ってみる ~データベースにアクセスする③~
【第十回】Spring Frameworkを使ってみる ~データベースにアクセスする④~

準備

テーブルの再作成

まずは、前回まで使用していたテーブルをいったん削除して下記のテーブル作成スクリプトを実行します。

CREATE TABLE department (
id INTEGER PRIMARY KEY,
name VARCHAR(40)
);
CREATE TABLE user (
id INTEGER PRIMARY KEY,
name VARCHAR(40),
department_id INTEGER,
FOREIGN KEY (department_id)
REFERENCES department (id)
);

テーブルにデータ挿入

下記のスクリプトを実行し、テーブルにデータを挿入します。


INSERT INTO department (id,name)
VALUES (1,'人事部');

INSERT INTO department (id,name)
VALUES (2,'営業部');

INSERT INTO user (id,name,department_id)
VALUES (1,'田中',1);

INSERT INTO user (id,name,department_id)
VALUES (2,'佐藤',1);

INSERT INTO user (id,name,department_id)
VALUES (3,'鈴木',2);

モデルの削除

前回の記事で作成したモデルを削除します。
delete-model
delete-model2

JPAを使用してモデル作成

モデルの作成

前々回と同様にJPAを使用してモデルを作成していきます。
「model」パッケージを右クリック⇒「New」⇒「other…」を選択します。
make-jpa-model

「JPA」⇒「JPA Entities from Tables」を選択します。
make-jpa-model2

Connectionを選択して、先ほど作成した「department」テーブルと「user」テーブルにチェックを入れます。
チェック後、「Finish」を選択します。
make-jpa-model3

modelパッケージ内にEntityが作成されました。
make-jpa-model4

モデルの内容確認

作成方法は前々回と同様ですが、今回は、テーブルにプライマリキーと外部キーがしっかりと張られています。
そのことによりJPAからテーブルを作成したときに、すでに結合した結果が取得できるようになっています。
具体的には作成されたモデルの下記の部分を見てみましょう。

User.java

package jp.ssie.helloworld.model;

import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the user database table.
*
*/
@Entity
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;

@Id
private int id;

private String name;

//bi-directional many-to-one association to Department
@ManyToOne
private Department department;

public User() {
}

public int getId() {
return this.id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Department getDepartment() {
return this.department;
}

public void setDepartment(Department department) {
this.department = department;
}

}

20行目、21行目に「@ManyToOne」アノテーションと「Department」クラスの変数が出来上がっています。
この記述があると「User」テーブルのデータを取得した際に、それに紐づく「Department」テーブルのデータを取得することができます。
つまり、テーブルの外部キーなどがしっかりと貼られていれば、SQLを記述することなくテーブルの結合した結果を取得することができます。
アノテーションの「@ManyToOne」は多対1という意味になります。
ここでは「ユーザ:多」に対し「部署:1」になります。
「Department.java」についても確認してみます。

Department.java

package jp.ssie.helloworld.model;

import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the department database table.
*
*/
@Entity
@NamedQuery(name="Department.findAll", query="SELECT d FROM Department d")
public class Department implements Serializable {
private static final long serialVersionUID = 1L;

@Id
private int id;

private String name;

//bi-directional many-to-one association to User
@OneToMany(mappedBy="department")
private List<User> users;

public Department() {
}

public int getId() {
return this.id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public List<User> getUsers() {
return this.users;
}

public void setUsers(List<User> users) {
this.users = users;
}

public User addUser(User user) {
getUsers().add(user);
user.setDepartment(this);

return user;
}

public User removeUser(User user) {
getUsers().remove(user);
user.setDepartment(null);

return user;
}

}

21行目、22行目で「User」テーブルと同様に、「@OneToMany」アノテーションと「User」クラスのリスト変数が出来上がっています。
Userと違い、「部署:1」に対し「ユーザ:多」になるので、それをあらわすアノテーションが付与されています。
また、「部署:1」に対し「ユーザ:多」なので、取得する「User」クラスはリストになっています。

出力内容の変更

ログイン後に前回出力した名前だけでなく、部署名を出力していきます。

LoginControllerの編集

ログイン時に取得する値に部署名を追加します。
JPAが結合を自動で行ってくれるので、取得した結果から「getDepartment」するだけで部署テーブルの内容を取得することができます。

LoginController.java

package jp.ssie.helloworld.web;

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

import jp.ssie.helloworld.form.LoginForm;
import jp.ssie.helloworld.model.User;
import jp.ssie.helloworld.repository.UserRepository;
import jp.ssie.helloworld.validation.GroupOrder;

@Controller
public class LoginController {
@Autowired
private UserRepository userRep;

@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Model model) {
return "index";
}

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(Model model, @Validated(GroupOrder.class) @ModelAttribute("loginForm") LoginForm loginForm, BindingResult result) {
if(result.hasErrors()) {
return "index";
}

List<User> userList = userRep.findById(loginForm.getUserId());

if(userList.size() > 0) {
model.addAttribute("userName", userList.get(0).getName());
model.addAttribute("departmentName", userList.get(0).getDepartment().getName());
return "top";
} else {
return "index";
}

}
}

39行目でとくに難しいことはせずに、EntityのGetterメソッドのみで部署名を取得していきます。

top.jspの編集

設定した部署名を画面に出力します。
top.jspを下記のように変更します。

top.jsp

<!DOCTYPE html>

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

<html>
<head>
<meta charset="utf-8">
<title>トップ</title>
</head>
<body>
ようこそ<c:out value="${departmentName}" />の<c:out value="${userName}" />さん
</body>
</html>

実行結果

実行

ユーザIDに「1」を入力します。
jpa-result

紐づく部署名が出力されています。
jpa-result2

ユーザIDに「3」を入力します。
jpa-result3

紐づく部署名が出力されています。
jpa-result4

非常に簡単にテーブルの結合を実現することができました。

次回について

今回はデータベースのテーブルを結合して値を取得しました。簡単なものであればこれで十分と思われるので、次回からは画面の出力について調査していきます。

  • このエントリーをはてなブックマークに追加

PAGE TOP