ホーム画面からユーザー一覧画面に遷移し、ユーザーの詳細を表示するアプリケーションを作成して、Spring JDBCの使い方について学びます⭐️
前回は、トランザクションの基本的な処理である宣言的トランザクション実装したので、今回は明示的トランザクションを学びます^^
構成は前回/これまでの記事を参考にしてください
⭐️前回の記事
Java・SpringBoot】宣言的トランザクション処理(SpringBootアプリケーション実践編20)
#明示的トランザクション
- 実践では宣言的トランザクションを使う
- Springが用意するトランザクションでは対応できない場合に、明示的トランザクションを使う
###明示的トランザクションの使い方
-
PlatformTransactionManagerクラス
- トランザクションを開始、コミットなどをするクラス
PlatformTransactionManager txManager;
//トランザクション開始
TransactionStatus status = txManager.getTransaction(def);
//コミット
txManager.commit(status);
-
DefaultTransactionDefinitionクラス
- トランザクションの設定をするクラス
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
//トランザクションの名前を設定
def.setName("UpdateUser");
//読取専用ではない設定
def.setReadOnly(false);
//トランザクションの伝播レベルをREQUIREDに設定
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
###明示的トランザクション実践
UserService.java
@Service
public class UserService {
//中略(全文は下記参考)
@Autowired
PlatformTransactionManager txManager;
//中略(全文は下記参考)
/**
* 1件更新用メソッド.
*/
public boolean updateOne(User user) throws DataAccessException {
//インスタンス生成
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
//設定
def.setName("UpdateUser");
def.setReadOnly(false);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//トランザクション開始
TransactionStatus status = txManager.getTransaction(def);
// 判定用変数
boolean result = false;
try {
// 1件更新
int rowNumber = dao.updateOne(user);
if (rowNumber > 0) {
// update成功
result = true;
}
}catch (Exception e){
txManager.rollback(status);
throw new DataAccessException("ERROR Update",e) {};
}
//コミット
txManager.commit(status);
return result;
}
//中略(全文は下記参考)
}
#SpringBootを起動してホーム画面確認!
- http://localhost:8080/home
- ユーザ一覧からユーザ詳細画面に移り、ユーザー名更新
- "Update Oyakata Neko"に名前を更新しても、ユーザ名が変わっていない(更新失敗)、トランザクションがロールバックできていることがわかりました〜〜!^^
- 明示的トランザクションは、AOP内でサービスクラスのメソッドを実行する前後で、トランザクションの開始/コミットをすればOK!
#(参考)コード全文
UserService.java
package com.example.demo.login.domain.service;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import com.example.demo.login.domain.model.User;
import com.example.demo.login.domain.repository.UserDao;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Service
public class UserService {
@Autowired
@Qualifier("UserDaoJdbcImpl")
UserDao dao;
@Autowired
PlatformTransactionManager txManager;
/**
* insert用メソッド.
*/
public boolean insert(User user) {
// insert実行
int rowNumber = dao.insertOne(user);
// 判定用変数
boolean result = false;
if (rowNumber > 0) {
// insert成功
result = true;
}
return result;
}
/**
* カウント用メソッド.
*/
public int count() {
return dao.count();
}
/**
* 全件取得用メソッド.
*/
public List<User> selectMany() {
// 全件取得
return dao.selectMany();
}
/**
* 1件取得用メソッド.
*/
public User selectOne(String userId) {
// selectOne実行
return dao.selectOne(userId);
}
/**
* 1件更新用メソッド.
*/
public boolean updateOne(User user) throws DataAccessException {
//インスタンス生成
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
//設定
def.setName("UpdateUser");
def.setReadOnly(false);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//トランザクション開始
TransactionStatus status = txManager.getTransaction(def);
// 判定用変数
boolean result = false;
try {
// 1件更新
int rowNumber = dao.updateOne(user);
if (rowNumber > 0) {
// update成功
result = true;
}
}catch (Exception e){
txManager.rollback(status);
throw new DataAccessException("ERROR Update",e) {};
}
//コミット
txManager.commit(status);
return result;
}
/**
* 1件削除用メソッド.
*/
public boolean deleteOne(String userId) {
// 1件削除
int rowNumber = dao.deleteOne(userId);
// 判定用変数
boolean result = false;
if (rowNumber > 0) {
// delete成功
result = true;
}
return result;
}
// ユーザー一覧をCSV出力する.
/**
* @throws DataAccessException
*/
public void userCsvOut() throws DataAccessException {
// CSV出力
dao.userCsvOut();
}
/**
* サーバーに保存されているファイルを取得して、byte配列に変換する.
*/
public byte[] getFile(String fileName) throws IOException {
// ファイルシステム(デフォルト)の取得
FileSystem fs = FileSystems.getDefault();
// ファイル取得
Path p = fs.getPath(fileName);
// ファイルをbyte配列に変換
byte[] bytes = Files.readAllBytes(p);
return bytes;
}
}