TOP →
Java →
spring → This Page
3.4.4.(Criteria API)(複数テーブルの結合) Spring+MVC+DB+Test構築サンプル
前提
このページに記載している内容は 2018/10/08 に書かれたものです。
掲載している画面や方法が将来的に変更されている場合があります。
また、掲載しているインストール方法は Windows 8.1 の場合です。
開発環境は
・Windows 8.1
・JDK 8
・STS(Spring Tool Suite) 3.9.5
・PostgreSQL 9.5.14
とします。
目次
1.Entityクラスの作成
2.Daoインタフェースの作成
3.Daoクラスの作成
4.Serviceインタフェースの作成
5.Serviceクラスの作成
6.TestController.java編集
7.index.jsp編集
8.確認実行
1.Entityクラスの作成
今回は「複数テーブルの結合」ということで、
準備編で用意したテーブル「staff」テーブルと「department」テーブルを使うことにします。
「staff」テーブルは「department」テーブルと外部結合でつながっています。
「staff」テーブルからみると「department」テーブルとの関係は「N:1」です。
(複数のスタッフが同じ1つの部門に属している状態)
通常は1テーブルにつき対応した1Entityクラスを作成しますが、
今回は2テーブルに対応したEntityクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.entity」と入力
・「Name」は「StaffAndDepartment」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「StaffAndDepartment.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.entity;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class StaffAndDepartment {
@Id
private Long id;
private String name;
private Integer age;
private Long deptid;
private String deptname;
public StaffAndDepartment() {
}
public StaffAndDepartment(Long id, String name, Integer age, Long deptid, String deptname) {
this();
this.id = id;
this.name = name;
this.age = age;
this.deptid = deptid;
this.deptname = deptname;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Long getDeptid() {
return deptid;
}
public void setDeptid(Long deptid) {
this.deptid = deptid;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
@Override
public String toString() {
return "[id=" + id + ",name=" + name + ",age=" + age
+ ",dept:id=" + deptid + ",dept:name=" + deptname + "]";
}
}
2テーブルのカラムに合わせて id, name, age, deptid, deptname をメンバフィールドに持ちます。
あとはコンストラクタと表示用の toString メソッドだけの簡単な構造です。
2.Daoインタフェースの作成
同じく1テーブルにつき対応した1DAOインタフェースを作成します。
プロジェクト名を右クリックして「New」>「Interface」を選択します。
「New Java Interface」ダイアログが表示されます。
・「Package」は「jp.mitchy.dao」と入力
・「Name」は「StaffAndDepartmentDao」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「StaffAndDepartmentDao.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.dao;
import java.util.List;
import jp.mitchy.entity.StaffAndDepartment;
public interface StaffAndDepartmentDao {
public List<StaffAndDepartment> getAllEntity();
}
今回は2テーブル全レコード取得のメソッドのみです
3.Daoクラスの作成
先ほど作成したインタフェースを実装したクラスを作成します。
同じく1テーブルにつき対応した1DAOクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.dao.impl」と入力
・「Name」は「StaffAndDepartmentDaoImpl」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「StaffAndDepartmentDaoImpl.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.dao.impl;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;
import org.springframework.stereotype.Repository;
// import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import jp.mitchy.dao.StaffAndDepartmentDao;
import jp.mitchy.entity.Department;
import jp.mitchy.entity.Staff;
import jp.mitchy.entity.StaffAndDepartment;
@Repository
public class StaffAndDepartmentDaoImpl implements StaffAndDepartmentDao {
@PersistenceContext
private EntityManager manager;
public StaffAndDepartmentDaoImpl() {
init();
}
public void init(){
// @Autowired がうまく機能しない場合は以下のコメントを外す
// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
public List<StaffAndDepartment> getAllEntity() {
System.out.println("getAllEntity()");
CriteriaBuilder builder = manager.getCriteriaBuilder();
CriteriaQuery<StaffAndDepartment> query = builder.createQuery(StaffAndDepartment.class);
Root<Staff> root = query.from(Staff.class);
Join<Staff, Department> join = root.join("department");
query.select(builder.construct(
StaffAndDepartment.class,
root.get("id"), root.get("name"), root.get("age"),
join.get("id"), join.get("name")));
return manager.createQuery(query).getResultList();
}
}
CriteriaQuery では結合結果となる StaffAndDepartment クラスを指定しています。
次に、基本テーブルを Staff テーブルとするため Root には Staff を指定しています。
そして Join で Staff テーブルと Department テーブルを指定して結合しています。
最後に結合結果とカラムを結びつけるために
builder.construct メソッドに結果型のクラスとカラムを引数に渡します。
メインテーブルのカラムは root.get("xxx")、
サブテーブルのカラムは join.get("xxx") で指定します。
4.Serviceインタフェースの作成
次にサービス層のインタフェース・クラスを作ります。
今回もまずはインタフェースを作成します。
プロジェクト名を右クリックして「New」>「Interface」を選択します。
「New Java Interface」ダイアログが表示されます。
・「Package」は「jp.mitchy.service」と入力
・「Name」は「StaffAndDepartmentService」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「StaffAndDepartmentService.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.service;
import jp.mitchy.dto.TestResultDto;
import jp.mitchy.entity.StaffAndDepartment;
public interface StaffAndDepartmentService {
public TestResultDto<StaffAndDepartment> execute();
}
TestResultDto を返す execute メソッドのみのシンプルなインタフェースです
5.Serviceクラスの作成
先ほど作成したインタフェースを実装したクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.service.impl」と入力
・「Name」は「StaffAndDepartmentServiceImpl」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「StaffAndDepartmentServiceImpl.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import jp.mitchy.dao.StaffAndDepartmentDao;
import jp.mitchy.dto.TestResultDto;
import jp.mitchy.entity.StaffAndDepartment;
import jp.mitchy.service.StaffAndDepartmentService;
@Service
public class StaffAndDepartmentServiceImpl implements StaffAndDepartmentService {
@Autowired
private StaffAndDepartmentDao dao;
public StaffAndDepartmentServiceImpl() {
init();
}
public void init(){
// @Autowired がうまく機能しない場合は以下のコメントを外す
// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
public TestResultDto<StaffAndDepartment> execute(){
TestResultDto<StaffAndDepartment> result = new TestResultDto<StaffAndDepartment>();
result.setEntity(null);
// SELECT 複数
List<StaffAndDepartment> list = dao.getAllEntity();
result.setList(list);
return result;
}
}
基本的に前の章で作成した内容から特に新しいものは出てきていないので
説明は割愛します。
6.TestController.java編集
jp.mitchy.controller にある TestController.java を変更し、
今回作成したサービスを呼び出して実行するようにします。
内容を以下のように書き換えて保存しましょう。
赤文字が前回から追加になる箇所です。
package jp.mitchy.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import jp.mitchy.dto.TestResultDto;
import jp.mitchy.entity.Attendance;
import jp.mitchy.entity.AttendancePk;
import jp.mitchy.entity.Department;
import jp.mitchy.entity.Staff;
import jp.mitchy.entity.StaffAndDepartment;
import jp.mitchy.service.AttendanceService;
import jp.mitchy.service.DepartmentService;
import jp.mitchy.service.StaffAndDepartmentService;
import jp.mitchy.service.StaffService;
@RequestMapping("/test/*")
@Controller
public class TestController {
@Autowired
private DepartmentService deptService;
@Autowired
private StaffService staffService;
@Autowired
private AttendanceService attendService;
@Autowired
private StaffAndDepartmentService staffDeptService;
@RequestMapping(value = "/dept", method = RequestMethod.GET)
public String dept(Model model) {
// ------------------------------
// 単テーブルのCURD確認
// ------------------------------
Department entity = new Department(4L, "新事業部");
// サービスの実行
TestResultDto<Department> dto = deptService.execute(entity);
// 結果をセット
model.addAttribute("data", dto.getEntity());
model.addAttribute("list", dto.getList());
// view/test/result.jsp を表示
return "test/result";
}
@RequestMapping(value = "/staff", method = RequestMethod.GET)
public String staff(Model model) {
// ------------------------------
// N:1 テーブルのCURD確認
// ------------------------------
Staff entity = new Staff(103L, "人事太郎3", 50, 1L);
// サービスの実行
TestResultDto<Staff> dto = staffService.execute(entity);
// 結果をセット
model.addAttribute("data", dto.getEntity());
model.addAttribute("list", dto.getList());
// view/test/result.jsp を表示
return "test/result";
}
@RequestMapping(value = "/attend", method = RequestMethod.GET)
public String attend(Model model) {
// ------------------------------
// 複合主キー テーブルのCURD確認
// ------------------------------
AttendancePk id = new AttendancePk(201L, 20180101);
Attendance entity = new Attendance(id, 1);
// サービスの実行
TestResultDto<Attendance> dto = attendService.execute(entity);
// 結果をセット
model.addAttribute("data", dto.getEntity());
model.addAttribute("list", dto.getList());
// view/test/result.jsp を表示
return "test/result";
}
@RequestMapping(value = "/staffdept", method = RequestMethod.GET)
public String staffdept(Model model) {
// ------------------------------
// 複数テーブルの結合
// ------------------------------
// SELECT 複数
TestResultDto<StaffAndDepartment> dto = staffDeptService.execute();
// 結果をセット
model.addAttribute("data", dto.getEntity());
model.addAttribute("list", dto.getList());
// view/test/result.jsp を表示
return "test/result";
}
}
こちらも基本的に前の章で作成したメソッドとほぼ同じなので
説明は割愛します。
7.index.jsp編集
最後に、作成した処理を呼び出せるように index.jsp を編集します。
src/main/webapp/index.jsp を開き、内容を以下のように書き換えて保存しましょう。
赤文字が前回から追加になる箇所です。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Welcome</title>
</head>
<body>
<c:url value="/test/dept" var="messageUrl1" />
<a href="${messageUrl1}">Department Test</a><br/>
<c:url value="/test/staff" var="messageUrl2" />
<a href="${messageUrl2}">Staff Test</a><br/>
<c:url value="/test/attend" var="messageUrl3" />
<a href="${messageUrl3}">Attendance Test</a><br/>
<c:url value="/test/staffdept" var="messageUrl4" />
<a href="${messageUrl4}">Staff and Department Test</a><br/>
</body>
</html>
8.確認実行
念のためにいつもの「Maven Clean」「Maven Install」をやっておきましょう。
エラーが出たら「Project」>「Clean」をやってから
再度「Maven Install」です。
次にプロジェクト名を右クリックして「Run As」>「Run On Server」を選択します。
少し時間がかかりますが「Console」に状況が表示されていきます。
しばらくすると内蔵ブラウザが立ち上がり、「Staff and Department Test」が表示されます。
「Staff and Department Test」のリンクをクリックしてみましょう。
リンク先 /test/staffdept に連動する TestController クラスの staffdept メソッドが呼び出され、
/WEB-INF/view/test/result.jsp が表示されることが確認できます。
テーブル操作も正常に実行されていますね。
(Consoleの出力内容も確認してみましょう)
以上で Criteria API を使った複数テーブルの結合の
サンプル構築は完了です。
ダウンロード
更新履歴
2018/10/08 新規作成
TOP →
Java →
spring → This Page