タイトル
TOPJavaspring → This Page

3.1.3.(JdbcTemplate)(複合主キーテーブルの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
とします。

本ページは先に以下の4ページの内容を実施してからの内容となります。
1.準備
2.共通部分構築
3.1.1.JdbcTemplate 単一テーブルのCRUD
3.1.2.JdbcTemplate N:1テーブルのCRUD

JdbcTemplate は SQL を発行して結果を返すだけのシンプルな機能しかないため、
実は本ページの「複合主キーテーブルのCRUD」は前々章の「単一テーブルのCRUD」となんら変わりません。
他のDBアクセス方法のページに章構成を合わせるために作っただけです。
そのため、適当に読み飛ばして次に進んでも大丈夫です。


目次

1.Entityクラスの作成
2.Daoインタフェースの作成
3.Daoクラスの作成
4.Serviceインタフェースの作成
5.Serviceクラスの作成
6.TestController.java編集
7.index.jsp編集
8.確認実行

1.Entityクラスの作成

今回は「複合主キーテーブルのCRUD」ということで、
準備編で用意したテーブル「attendance」テーブルを使うことにします。
「attendance」テーブルは staffid, yyyymmdd カラムの2つがキー(複合主キー)となります。
図:attendance

1テーブルにつき対応した1Entityクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
図:STS

「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.entity」と入力
・「Name」は「Attendance」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
図:New Java Class

作成された「Attendance.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.entity;

public class Attendance {
	private Long staffid;
	private Integer yyyymmdd;
	private Integer state;
	
	public Attendance() {
	}
	
	public Attendance(Long staffid, Integer yyyymmdd, Integer state) {
		this();
		this.staffid = staffid;
		this.yyyymmdd = yyyymmdd;
		this.state = state;
	}

	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 Integer getState() {
		return state;
	}

	public void setState(Integer state) {
		this.state = state;
	}
	
	@Override
	public String toString() {
		return "[staffid=" + staffid + ",yyyymmdd=" + yyyymmdd
				+ ",state=" + state + "]";
	}
	
}
テーブルのカラムに合わせて staffid, yyyymmdd, state をメンバフィールドに持ちます。
あとはコンストラクタと表示用の toString メソッドだけの簡単な構造です。


3.Daoインタフェースの作成

同じく1テーブルにつき対応した1DAOインタフェースを作成します。
プロジェクト名を右クリックして「New」>「Interface」を選択します。
図:STS

「New Java Interface」ダイアログが表示されます。
・「Package」は「jp.mitchy.dao」と入力
・「Name」は「AttendanceDao」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
図:New Java Interface

作成された「AttendanceDao.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.dao;

import java.util.List;

import jp.mitchy.entity.Attendance;

public interface AttendanceDao {
	public List<Attendance> getAllEntity();
	public Attendance findById(Long staffid, Integer yyyymmdd);
	public void addEntity(Attendance entity);
	public void updateEntity(Attendance entity);
	public void removeEntity(Attendance data);
	public void removeEntity(Long staffid, Integer yyyymmdd);
}
今回も今までと同じでそれぞれ
・全レコード取得
・1レコード取得
・レコード追加
・レコード更新
・レコード削除(引数がエンティティ)
・レコード削除(引数がID)
です


4.Daoクラスの作成

先ほど作成したインタフェースを実装したクラスを作成します。
同じく1テーブルにつき対応した1DAOクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
図:STS

「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.dao.impl」と入力
・「Name」は「AttendanceDaoImpl」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
図:New Java Class

作成された「AttendanceDaoImpl.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.dao.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
// import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import jp.mitchy.dao.AttendanceDao;
import jp.mitchy.entity.Attendance;

@Repository
public class AttendanceDaoImpl implements AttendanceDao {
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	public AttendanceDaoImpl() {
		init();
	}
	
	public void init(){
		// @Autowired がうまく機能しない場合は以下のコメントを外す
		// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
	}

	public List<Attendance> getAllEntity() {
		System.out.println("getAllEntity()");
		return jdbcTemplate.query("SELECT * FROM Attendance",
				new BeanPropertyRowMapper<Attendance>(Attendance.class));
	}

	public Attendance findById(Long staffid, Integer yyyymmdd) {
		return jdbcTemplate.queryForObject("SELECT * FROM Attendance WHERE staffid = ? AND yyyymmdd = ?",
				new Object[] { staffid, yyyymmdd } ,
				new BeanPropertyRowMapper<Attendance>(Attendance.class));
	}
	
	public void addEntity(Attendance entity) {
		System.out.println("addEntity(entity)");
		jdbcTemplate.update("INSERT INTO Attendance VALUES(?, ?, ?)",
				entity.getStaffid(), entity.getYyyymmdd(), entity.getState());
	}

	public void updateEntity(Attendance entity) {
		System.out.println("updateEntity(entity)");
		jdbcTemplate.update("UPDATE Attendance SET state = ? WHERE staffid = ? AND yyyymmdd = ?",
				entity.getState(), entity.getStaffid(), entity.getYyyymmdd());
	}

	public void removeEntity(Attendance entity) {
		System.out.println("removeEntity(entity)");
		jdbcTemplate.update("DELETE FROM Attendance WHERE staffid = ? AND yyyymmdd = ?",
				entity.getStaffid(), entity.getYyyymmdd());
	}

	public void removeEntity(Long staffid, Integer yyyymmdd) {
		System.out.println("removeEntity(id)");
		jdbcTemplate.update("DELETE FROM Attendance WHERE staffid = ? and yyyymmdd = ?",
				staffid, yyyymmdd);
	}

}
特に改めて解説すべきところはないので説明は割愛します。


5.Serviceインタフェースの作成

次にサービス層のインタフェース・クラスを作ります。
今回もまずはインタフェースを作成します。
プロジェクト名を右クリックして「New」>「Interface」を選択します。
図:STS

「New Java Interface」ダイアログが表示されます。
・「Package」は「jp.mitchy.service」と入力
・「Name」は「AttendanceService」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
図:New Java Interface

作成された「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 メソッドのみのシンプルなインタフェースです


6.Serviceクラスの作成

先ほど作成したインタフェースを実装したクラスを作成します。
プロジェクト名を右クリックして「New」>「Class」を選択します。
図:STS

「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.service.impl」と入力
・「Name」は「AttendanceServiceImpl」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
図:New Java Class

作成された「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.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.getStaffid(), entity.getYyyymmdd());
		
		// SELECT 単体
		Attendance entity2 = dao.findById(102L, 20180801);
		result.setEntity(entity2);
		
		// SELECT 複数
		List<Attendance> list = dao.getAllEntity();
		result.setList(list);

		return result;
	}
	
}
こちらも基本的に前の章で作成した「DepartmentServiceImpl」とほぼ同じなので
説明は割愛します。


7.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.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 attendService;
	
	@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確認
		// ------------------------------
		
		Attendance entity = new Attendance(201L, 20180101, 1);
		
		// サービスの実行
		TestResultDto<Attendance> dto = attendService.execute(entity);

		// 結果をセット
		model.addAttribute("data", dto.getEntity());
		model.addAttribute("list", dto.getList());
		
		// view/test/result.jsp を表示
		return "test/result";
	}
	
}

こちらも基本的に前の章で作成したメソッドとほぼ同じなので
説明は割愛します。


8.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>


9.確認実行

念のためにいつもの「Maven Clean」「Maven Install」をやっておきましょう。
エラーが出たら「Project」>「Clean」をやってから
再度「Maven Install」です。

次にプロジェクト名を右クリックして「Run As」>「Run On Server」を選択します。
図:STS

少し時間がかかりますが「Console」に状況が表示されていきます。
しばらくすると内蔵ブラウザが立ち上がり、「Attendance Test」が表示されます。
図:ブラウザ

「Attendance Test」のリンクをクリックしてみましょう。
リンク先 /test/attend に連動する TestController クラスの attend メソッドが呼び出され、
/WEB-INF/view/test/result.jsp が表示されることが確認できます。
テーブル操作も正常に実行されていますね。
(Consoleの出力内容も確認してみましょう)
図:ブラウザ

以上で JdbcTemplate を使った複合主キーテーブルのCRUDの
サンプル構築は完了です。


ダウンロード

作成したプロジェクトのソースをダウンロードできます。
313WebDbSample1JdbcTemplate.zip


更新履歴

2018/10/06 新規作成

TOPJavaspring → This Page