TOP →
Java →
spring → This Page
3.3.3.(JpaRepository)(複合主キーテーブルのCRUD) Spring+MVC+DB+Test構築サンプル
前提
このページに記載している内容は 2018/10/06 に書かれたものです。
掲載している画面や方法が将来的に変更されている場合があります。
また、掲載しているインストール方法は Windows 8.1 の場合です。
開発環境は
・Windows 8.1
・JDK 8
・STS(Spring Tool Suite) 3.9.5
・PostgreSQL 9.5.14
とします。
目次
1.PrimaryKeyクラスの作成
2.Entityクラスの作成
3.Repositoryインタフェースの作成
4.Daoインタフェースの作成
5.Daoクラスの作成
6.Serviceインタフェースの作成
7.Serviceクラスの作成
8.TestController.java編集
9.index.jsp編集
10.確認実行
1.PrimaryKeyクラスの作成
今回は「複合主キーテーブルのCRUD」ということで、
準備編で用意したテーブル「attendance」テーブルを使うことにします。
「attendance」テーブルは staffid, yyyymmdd カラムの2つがキー(複合主キー)となります。
JpaRepository(というよりも JPA)を使う場合かつ複合主キーのテーブルを扱う場合、
複合主キーに対応したPrimaryKeyクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.entity」と入力
・「Name」は「AttendancePk」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「AttendancePk.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
@Embeddable
public class AttendancePk implements Serializable {
private static final long serialVersionUID = 1L;
@Column
private Long staffid;
@Column
private Integer yyyymmdd;
public AttendancePk() {
}
public AttendancePk(Long staffid, Integer yyyymmdd) {
this();
this.staffid = staffid;
this.yyyymmdd = yyyymmdd;
}
public Long getStaffid() {
return staffid;
}
public void setStaffid(Long staffid) {
this.staffid = staffid;
}
public Integer getYyyymmdd() {
return yyyymmdd;
}
public void setYyyymmdd(Integer yyyymmdd) {
this.yyyymmdd = yyyymmdd;
}
public int hashCode() {
int hashCode = 0;
if (staffid != null) {
hashCode ^= staffid.hashCode();
}
if (yyyymmdd != null) {
hashCode ^= yyyymmdd.hashCode();
}
return hashCode;
}
public boolean equals(Object obj) {
if (!(obj instanceof AttendancePk)) {
return false;
}
AttendancePk target = (AttendancePk) obj;
return ((this.staffid == null) ? (target.staffid == null) : this.staffid.equals(target.staffid))
&& ((this.yyyymmdd == null) ? (target.yyyymmdd == null) : this.yyyymmdd.equals(target.yyyymmdd));
}
}
クラス名の上に @Embeddable アノテーションをつけています。
これで別のエンティティクラスに「組み込む」ことができます。
「組み込む」ためにはさらに
・Serializable インタフェースを実装する
・hashCode メソッドを実装する
・equals メソッドを実装する
・@Id アノテーションは使わずに @Column アノテーションを使う
(@Id アノテーションはエンティティクラス側で使う)
というポイントがあります。
テーブルの複合主キーに合わせて staffid, yyyymmdd をメンバフィールドに持ちます。
前述のように、主キーであっても @Column アノテーションを使います。
(@Id アノテーションは使わない!)
hashCode メソッド、equals メソッドは本サンプルを確認して下さい。
「こういうもんだ」と思って、自分で新しいPrimaryKeyクラスを作る際は
参考にしながら作って下さい。
2.Entityクラスの作成
いつものごとくテーブルに対応したEntityクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.entity」と入力
・「Name」は「Attendance」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「Attendance.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.entity;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name="attendance")
public class Attendance {
@EmbeddedId
private AttendancePk id;
@Column(nullable=false)
private int state;
public Attendance() {
}
public Attendance(AttendancePk id, int state) {
this();
this.id = id;
this.state = state;
}
public AttendancePk getId() {
return id;
}
public void setId(AttendancePk id) {
this.id = id;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
@Override
public String toString() {
return "[staffid=" + id.getStaffid() + ",yyyymmdd=" + id.getYyyymmdd()
+ ",state=" + state + "]";
}
}
前章と同じ箇所は説明を割愛します。
テーブルの複合主キーとして先ほど作成した AttendancePk クラスを
@EmbeddedId アノテーションをつけてメンバフィールドに持ちます。
これで複合主キーを組み込めました。
あとは残りのカラム state をメンバフィールドに持っているだけです。
他は今までのエンティティクラスと変わりありません。
3.Repositoryインタフェースの作成
次にリポジトリをインタフェースとして作成します。
同じく1テーブルにつき対応した1リポジトリ・インタフェースを作成します。
プロジェクト名を右クリックして「New」>「Interface」を選択します。
「New Java Interface」ダイアログが表示されます。
・「Package」は「jp.mitchy.repository」と入力
・「Name」は「AttendanceRepository」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「AttendanceRepository.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import jp.mitchy.entity.Attendance;
import jp.mitchy.entity.AttendancePk;
@Repository
public interface AttendanceRepository extends JpaRepository<Attendance, AttendancePk> {
}
前章と同じ箇所は説明を割愛します。
extends JpaRepository の右側のカッコ内が
Attendance と AttendancePk になっています。
2つ目がキーになるので先ほど作成した PrimaryKeyクラス を指定しています。
4.Daoインタフェースの作成
同じく1テーブルにつき対応した1DAOインタフェースを作成します。
プロジェクト名を右クリックして「New」>「Interface」を選択します。
「New Java Interface」ダイアログが表示されます。
・「Package」は「jp.mitchy.dao」と入力
・「Name」は「AttendanceDao」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「AttendanceDao.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.dao;
import java.util.List;
import jp.mitchy.entity.Attendance;
import jp.mitchy.entity.AttendancePk;
public interface AttendanceDao {
public List<Attendance> getAllEntity();
public Attendance findById(AttendancePk id);
public void addEntity(Attendance entity);
public void updateEntity(Attendance entity);
public void removeEntity(Attendance data);
public void removeEntity(AttendancePk id);
}
今回も今までと同じでそれぞれ
・全レコード取得
・1レコード取得
・レコード追加
・レコード更新
・レコード削除(引数がエンティティ)
・レコード削除(引数がID)
です
ただし、findById と removeEntity の引数は
PrimaryKeyクラスになっています。
5.Daoクラスの作成
先ほど作成したインタフェースを実装したクラスを作成します。
同じく1テーブルにつき対応した1DAOクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.dao.impl」と入力
・「Name」は「AttendanceDaoImpl」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「AttendanceDaoImpl.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.dao.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
// import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import jp.mitchy.dao.AttendanceDao;
import jp.mitchy.entity.Attendance;
import jp.mitchy.entity.AttendancePk;
import jp.mitchy.repository.AttendanceRepository;
@Repository
public class AttendanceDaoImpl implements AttendanceDao {
@Autowired
private AttendanceRepository repository;
public AttendanceDaoImpl() {
init();
}
public void init(){
// @Autowired がうまく機能しない場合は以下のコメントを外す
// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
public List<Attendance> getAllEntity() {
System.out.println("getAllEntity()");
return repository.findAll();
}
public Attendance findById(AttendancePk id) {
System.out.println("findById(AttendancePk)");
return repository.findOne(id);
}
public void addEntity(Attendance entity) {
System.out.println("addEntity(entity)");
repository.saveAndFlush(entity);
}
public void updateEntity(Attendance entity) {
System.out.println("updateEntity(entity)");
repository.saveAndFlush(entity);
}
public void removeEntity(Attendance entity) {
System.out.println("removeEntity(entity)");
repository.delete(entity);
}
public void removeEntity(AttendancePk id) {
System.out.println("removeEntity(AttendancePk)");
Attendance entity = repository.findOne(id);
repository.delete(entity);
}
}
前章からとクラスやメソッドが変わっただけなので説明を割愛します。
6.Serviceインタフェースの作成
次にサービス層のインタフェース・クラスを作ります。
今回もまずはインタフェースを作成します。
プロジェクト名を右クリックして「New」>「Interface」を選択します。
「New Java Interface」ダイアログが表示されます。
・「Package」は「jp.mitchy.service」と入力
・「Name」は「AttendanceService」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「AttendanceService.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.service;
import jp.mitchy.dto.TestResultDto;
import jp.mitchy.entity.Attendance;
public interface AttendanceService {
public TestResultDto<Attendance> execute(Attendance entity);
}
エンティティを引数とし、TestResultDto を返す execute メソッドのみのシンプルなインタフェースです
7.Serviceクラスの作成
先ほど作成したインタフェースを実装したクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.service.impl」と入力
・「Name」は「AttendanceServiceImpl」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「AttendanceServiceImpl.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.AttendanceDao;
import jp.mitchy.dto.TestResultDto;
import jp.mitchy.entity.Attendance;
import jp.mitchy.entity.AttendancePk;
import jp.mitchy.service.AttendanceService;
@Service
public class AttendanceServiceImpl implements AttendanceService {
@Autowired
private AttendanceDao dao;
public AttendanceServiceImpl() {
init();
}
public void init(){
// @Autowired がうまく機能しない場合は以下のコメントを外す
// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
public TestResultDto<Attendance> execute(Attendance entity) {
TestResultDto<Attendance> result = new TestResultDto<Attendance>();
// INSERT
dao.addEntity(entity);
// UPDATE
entity.setState(2);
dao.updateEntity(entity);
// DELETE
dao.removeEntity(entity.getId());
// SELECT 単体
AttendancePk id2 = new AttendancePk(102L, 20180801);
Attendance entity2 = dao.findById(id2);
result.setEntity(entity2);
// SELECT 複数
List<Attendance> list = dao.getAllEntity();
result.setList(list);
return result;
}
}
基本的に前の章で作成した内容から特に新しいものは出てきていないので
説明は割愛します。
8.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.service.AttendanceService;
import jp.mitchy.service.DepartmentService;
import jp.mitchy.service.StaffService;
@RequestMapping("/test/*")
@Controller
public class TestController {
@Autowired
private DepartmentService deptService;
@Autowired
private StaffService staffService;
@Autowired
private AttendanceService AttendanceService;
@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 = AttendanceService.execute(entity);
// 結果をセット
model.addAttribute("data", dto.getEntity());
model.addAttribute("list", dto.getList());
// view/test/result.jsp を表示
return "test/result";
}
}
こちらも基本的に前の章で作成したメソッドとほぼ同じなので
説明は割愛します。
9.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/Attendance" var="messageUrl2" />
<a href="${messageUrl2}">Staff Test</a><br/>
<c:url value="/test/attend" var="messageUrl3" />
<a href="${messageUrl3}">Attendance Test</a><br/>
</body>
</html>
10.確認実行
念のためにいつもの「Maven Clean」「Maven Install」をやっておきましょう。
エラーが出たら「Project」>「Clean」をやってから
再度「Maven Install」です。
次にプロジェクト名を右クリックして「Run As」>「Run On Server」を選択します。
少し時間がかかりますが「Console」に状況が表示されていきます。
しばらくすると内蔵ブラウザが立ち上がり、「Attendance Test」と表示されます。
「Attendance Test」のリンクをクリックしてみましょう。
リンク先 /test/attend に連動する TestController クラスの attend メソッドが呼び出され、
/WEB-INF/view/test/result.jsp が表示されることが確認できます。
テーブル操作も正常に実行されていますね。
(Consoleの出力内容も確認してみましょう)
以上で JpaRepository を使った複合主キーテーブルのCRUDの
サンプル構築は完了です。
ダウンロード
更新履歴
2018/10/06 新規作成
TOP →
Java →
spring → This Page