前回の第九回ではデータベースに接続し絞込みを行いログイン処理を実装しました。
今回は、テーブルの結合をしてデータを取得していきます。
Spring Framework連載記事 目次
【第一回】Spring Frameworkを使ってみる ~Spring Framework概要と準備~
【第二回】Spring Frameworkを使ってみる ~プロジェクト作成からビルドまで~
【第三回】Spring Frameworkを使ってみる ~サーバで実行~
【第四回】Spring Frameworkを使ってみる ~画面遷移~
【第五回】Spring Frameworkを使ってみる ~データ受け渡し~
【第六回】Spring Frameworkを使ってみる ~入力値チェック~
【第七回】Spring Frameworkを使ってみる ~データベースにアクセスする①~
【第八回】Spring Frameworkを使ってみる ~データベースにアクセスする②~
【第九回】Spring Frameworkを使ってみる ~データベースにアクセスする③~
【第十回】Spring Frameworkを使ってみる ~データベースにアクセスする④~
準備
テーブルの再作成
まずは、前回まで使用していたテーブルをいったん削除して下記のテーブル作成スクリプトを実行します。
1 2 3 4 5 6 7 8 9 10 11 | 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) ); |
テーブルにデータ挿入
下記のスクリプトを実行し、テーブルにデータを挿入します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!DOCTYPE html> <%@ page language= "java" contentType= "text/html; charset=UTF-8" pageEncoding= "UTF-8" %> <html> <head> <meta charset= "utf-8" > <title>トップ</title> </head> <body> ようこそ<c:out value= "${departmentName}" />の<c:out value= "${userName}" />さん </body> </html> |
実行結果
実行
非常に簡単にテーブルの結合を実現することができました。
次回について
今回はデータベースのテーブルを結合して値を取得しました。簡単なものであればこれで十分と思われるので、次回からは画面の出力について調査していきます。