TOP →
Java →
spring → This Page
3.3.5.(JpaRepository)(トランザクション制御+エラーページ) Spring+MVC+DB+Test構築サンプル
前提
このページに記載している内容は 2018/10/14 に書かれたものです。
掲載している画面や方法が将来的に変更されている場合があります。
また、掲載しているインストール方法は Windows 8.1 の場合です。
開発環境は
・Windows 8.1
・JDK 8
・STS(Spring Tool Suite) 3.9.5
・PostgreSQL 9.5.14
とします。
目次
1.application-config.xml編集
2.Serviceクラスの変更1
3.Serviceクラスの変更2
4.ErrorController.javaの作成
5.error.jspの作成
6.確認実行
1.application-config.xml編集
application-config.xml にトランザクション制御関連情報を設定します。
/src/main/resources/spring
フォルダにある
application-config.xml
をダブルクリックして開きましょう。
開いたら下のタブを「Source」にします。
(最初から「Source」になっている場合もあります)
以下の内容に書き換えて保存しましょう。
赤文字が前回から追加になる箇所です。
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties" />
<context:annotation-config />
<context:component-scan base-package="jp.mitchy"/>
<jpa:repositories base-package="jp.mitchy.repository" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="database" value="POSTGRESQL" />
</bean>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
<tx:annotation-driven transaction-manager="transactionManager" />
はトランザクション関連のアノテーションを使うための設定です。
2.Serviceクラスの変更1
「jp.mitchy.service.impl」パッケージにある「DepartmentServiceImpl」クラスを変更しましょう。
「DepartmentServiceImpl.java」を開いて、内容を以下のように書き換えて保存しましょう。
赤文字が前回から追加になる箇所です。
package jp.mitchy.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
//import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import jp.mitchy.dao.DepartmentDao;
import jp.mitchy.dto.TestResultDto;
import jp.mitchy.entity.Department;
import jp.mitchy.service.DepartmentService;
@Service
public class DepartmentServiceImpl implements DepartmentService {
@Autowired
private DepartmentDao dao;
public DepartmentServiceImpl() {
init();
}
public void init(){
// @Autowired がうまく機能しない場合は以下のコメントを外す
// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
@Transactional(readOnly=false, propagation=Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
public TestResultDto<Department> execute(Department entity) {
TestResultDto<Department> result = new TestResultDto<Department>();
// INSERT
dao.addEntity(entity);
// UPDATE
entity.setName("廃止");
dao.updateEntity(entity);
// DELETE
dao.removeEntity(entity.getId());
// SELECT 単体
Department entity2 = dao.findById(2L);
result.setEntity(entity2);
// SELECT 複数
List<Department> list = dao.getAllEntity();
result.setList(list);
return result;
}
}
execute メソッドに @Transactional アノテーションをつけています。
これでこのメソッドがトランザクション制御されます。
readOnly=false をつけることで更新が可能となります。
(デフォルトでfalseなので省略可能です)
propagation=Propagation.REQUIRES_NEW をつけることで常に新規にトランザクションを新規開始します。
propagation=Propagation.REQUIRES にすると、トランザクションが開始されていればそのトランザクションを利用し、
開始されていなければ新規開始します。
rollbackFor=Exception.class をつけることで例外発生時にロールバックされます。
rollbackFor=XxxException.class のようにすると XxxException 例外が発生したときだけロールバックされます。
3.Serviceクラスの変更2
「jp.mitchy.service.impl」パッケージにある「StaffServiceImpl」クラスを変更しましょう。
「StaffServiceImpl.java」を開いて、内容を以下のように書き換えて保存しましょう。
赤文字が前回から追加になる箇所です。
こちらはトランザクション制御がちゃんと機能しているか分かるように
わざと例外が発生するようにします。
package jp.mitchy.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import jp.mitchy.dao.StaffDao;
import jp.mitchy.dto.TestResultDto;
import jp.mitchy.entity.Staff;
import jp.mitchy.service.StaffService;
@Service
public class StaffServiceImpl implements StaffService {
@Autowired
private StaffDao dao;
public StaffServiceImpl() {
init();
}
public void init(){
// @Autowired がうまく機能しない場合は以下のコメントを外す
// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
@Transactional(readOnly=false, propagation=Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
public TestResultDto<Staff> execute(Staff entity) {
TestResultDto<Staff> result = new TestResultDto<Staff>();
// INSERT
dao.addEntity(entity);
// UPDATE
// わざと失敗(桁あふれ)
entity.setName("123456789012345678901234567890");
dao.updateEntity(entity);
// DELETE
dao.removeEntity(entity.getId());
// SELECT 単体
Staff entity2 = dao.findById(102L);
result.setEntity(entity2);
// SELECT 複数
List<Staff> list = dao.getAllEntity();
result.setList(list);
return result;
}
}
4.ErrorController.javaの作成
次に例外発生時に自動で動作するエラー用コントローラ・クラスを作ります。
プロジェクト名を右クリックして「New」>「Class」を選択します。
「New Java Class」ダイアログが表示されます。
・「Package」は「jp.mitchy.controller」と入力
・「Name」は「ErrorController」と入力
・それ以外の項目はそのまま
「Finish」ボタンを押します。
作成された「ErrorController.java」が開くので、内容を以下のように書き換えて保存しましょう。
package jp.mitchy.controller;
import org.springframework.dao.DataAccessException;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class ErrorController {
/**
* DB操作例外発生時にエラーページに遷移
*
* @param model
* @return 表示jsp
*/
@ExceptionHandler(DataAccessException.class)
public String dataAccessExceptionHandler(Model model) {
model.addAttribute("msg", "データベースの操作に失敗しました。");
// view/common/error.jsp を表示
return "common/error";
}
/**
* 例外発生時にエラーページに遷移
*
* @param model
* @return 表示jsp
*/
@ExceptionHandler(Throwable.class)
public String throwableHandler(Model model) {
model.addAttribute("msg", "例外が発生しました。");
// view/common/error.jsp を表示
return "common/error";
}
}
クラス名の上に @ControllerAdvice アノテーションをつけています。
これをつけることによってコントローラーをまたいで横断的に様々なハンドリングができるようになります。
各メソッドの上に @ExceptionHandler アノテーションをつけています。
これをつけることによって例外をハンドリングできるようになります。
アノテーションのカッコ内にハンドリングしたい例外クラスを指定しています。
dataAccessExceptionHandler メソッドには DataAccessException.class クラスを指定しているので
DB関連例外が発生した場合に動作します。
throwableHandler メソッドには Throwable.class クラスを指定しているので
その他の全ての例外が発生した場合に動作します。
ともに戻り値として遷移先のJSP(view/common/error.jsp)を指定しています。
5.error.jspの作成
最後に例外が発生した際に表示されるエラー用のページ(JSP)を作成します。
プロジェクト名を右クリックして「New」>「Other」を選択します。
「New」ダイアログが表示されます。
ツリーから「Web」>「JSP File」を選択して「Next」ボタンを押します。
「New JSP File」画面でフォルダを
src/main/webapp/WEB-INF/view/common/
とし、「File name」を「error.jsp」として「Finish」ボタンを押します。
「error.jsp」の内容を以下のように書き換えて保存しましょう。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<title>error</title>
</head>
<body>
<h1>
${msg}
</h1>
</body>
</html>
受け取ったメッセージを表示するだけのシンプルな画面です。
6.確認実行
念のためにいつもの「Maven Clean」「Maven Install」をやっておきましょう。
エラーが出たら「Project」>「Clean」をやってから
再度「Maven Install」です。
次にプロジェクト名を右クリックして「Run As」>「Run On Server」を選択します。
少し時間がかかりますが「Console」に状況が表示されていきます。
しばらくすると内蔵ブラウザが立ち上がり、下記の画面が表示されます。
まずは「Department Test」のリンクをクリックしてみましょう。
こちらは正常動作するサービスを呼び出すので変更前と同じくDB取得結果が表示されます。
前の画面に戻って「Staff Test」のリンクをクリックしてみましょう。
こちらは重複エラーでDB操作例外が発生するサービスを呼び出すので
エラー画面に遷移することが確認できます。
(Consoleの出力内容も確認してみましょう)
PostgreSQLの中身を確認したり、Serviceクラスを元に戻してテスト実行したりして、
先ほどの例外発生時にちゃんとロールバックされていることを確認しましょう。
以上で JpaRepository を使ったトランザクション制御+エラーページの
サンプル構築は完了です。
ダウンロード
更新履歴
2018/10/14 新規作成
TOP →
Java →
spring → This Page