Web系開発メモ

Java, JavaScript, CSS, HTML などの記事を書いています。

SpringBoot入門:トランザクションの管理

Spring Boot の Webアプリで、RDBトランザクションを管理する方法を書きます。Spring Frameworkアノテーション @Transactional を使って管理します。

前提

この記事は、記事「JPAでデータアクセス」の資源(ビルドファイル、クラス等)を利用しています。必要に応じて参照して頂けると嬉しいです。

手順1. コントローラの作成

リクエストを受け付けて、データを操作するクラスです。

gssb-rdb/src/main/java/gssb/rdb/controller/TxMemoController.java

package gssb.rdb.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import gssb.rdb.model.Memo;
import gssb.rdb.repository.MemoRepository;

@RestController
@RequestMapping(path="/tx")
public class TxMemoController {

  @Autowired MemoRepository repository;

  // メモを1つ作成して、その後でエラーを発生させるメソッド
  private void create(Memo memo) {
    repository.save(memo);
    repository.save(new Memo()); // text の NotEmpty でエラー。
  }

  // トランザクションを管理する。
  @Transactional
  @RequestMapping(path="/on/memos", method=RequestMethod.POST)
  public void txOn(@RequestBody Memo memo) {
    create(memo);
  }

  // トランザクションを管理しない。
  @RequestMapping(path="/off/memos", method=RequestMethod.POST)
  public void txOff(@RequestBody Memo memo) {
    create(memo);
  }
}

処理結果を比較するために、@Transactional を宣言するメソッドと、宣言しないメソッドを用意しました。

本格的なアプリだと、サービスクラスに処理とトランザクション宣言を実装することがあります。

手順2. 起動

事前に PostgreSQL を起動してから、次のコマンドでアプリを起動します。

gssb-rdb > mvn spring-boot:run

手順3. 確認

動作確認には curlpsql を使います。事前に psql で Memo テーブルを空にしておきます。

実行コマンド

spring=> delete from memo;

手順3.1. トランザクション管理の確認

curl を使って、トランザクションを管理するメソッドを呼び出します。メモを1つ登録して、エラーが発生します。

実行コマンド(※ JSON 内のエスケープ文字「\」は Windows で必要)

curl -H "Content-Type: application/json" -d "{\"text\":\"Data\"}" http://localhost:8080/tx/on/memos -X POST

実行結果

{"timestamp":1465023216817,"status":500,"error":"Internal Server Error","exception":"javax.validation....

トランザクションロールバックされるので、メモは1つも登録されていないはずです。psql で確認します。

実行コマンド

spring=> select * from memo;

実行結果

 id | text | version | updated_time | created_time
----+------+---------+--------------+--------------
(0 行)

手順3.2. トランザクション非管理の確認

次に、トランザクションを管理しないメソッドを呼び出します。

実行コマンド

curl -H "Content-Type: application/json" -d "{\"text\":\"Data\"}" http://localhost:8080/tx/off/memos -X POST

実行結果

{"timestamp":1465023445275,"status":500,"error":"Internal Server Error","exception":"javax.validation....

ロールバックされない(BEGIN もない)ので、メモが1つ登録されているはずです。psql で確認してみます。

実行コマンド

spring=> select * from memo;

実行結果

 id | text | version |      updated_time       |      created_time
----+------+---------+-------------------------+-------------------------
  6 | Data |       0 | 2016-06-04 15:57:25.244 | 2016-06-04 15:57:25.244
(1 行)

ソースコード

gssb-rdb - GitHub
※ プロジェクト名の gssb は、Getting Started Spring Boot の略です。