前回の第九回ではデータベースに接続し絞込みを行いログイン処理を実装しました。
今回は、テーブルの結合をしてデータを取得していきます。
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);
モデルの削除
JPAを使用してモデル作成
モデルの作成
前々回と同様にJPAを使用してモデルを作成していきます。
「model」パッケージを右クリック⇒「New」⇒「other…」を選択します。

「JPA」⇒「JPA Entities from Tables」を選択します。

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

モデルの内容確認
作成方法は前々回と同様ですが、今回は、テーブルにプライマリキーと外部キーがしっかりと張られています。
そのことにより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>
実行結果
実行
非常に簡単にテーブルの結合を実現することができました。
次回について
今回はデータベースのテーブルを結合して値を取得しました。簡単なものであればこれで十分と思われるので、次回からは画面の出力について調査していきます。






