トランザクション
Doma はローカルトランザクションをサポートしています。このドキュメントでは、ローカルトランザクションの設定方法と使用方法について説明します。
グローバルトランザクションを使用する場合は、JTA (Java Transaction API) をサポートするフレームワークまたはアプリケーションサーバーを使用してください。
設定クラスの定義 も参照してください。
設定
ローカル トランザクションを使用するには、次の条件が必要です。
ConfigのgetDataSourceからLocalTransactionDataSourceを返します。コンストラクターで上記の
LocalTransactionDataSourceを使用してLocalTransactionManagerを生成します上記の
LocalTransactionManagerを使用してデータベースアクセスを制御します
LocalTransactionManager を生成・取得する方法はいくつかありますが、最も簡単な方法は Config 実装クラスのコンストラクタ内で生成し、 Config 実装クラスをシングルトンにする方法です。
以下に例を示します。
public class DbConfig implements Config {
private static final DbConfig CONFIG = new DbConfig();
private final Dialect dialect;
private final LocalTransactionDataSource dataSource;
private final TransactionManager transactionManager;
private DbConfig() {
dialect = new H2Dialect();
dataSource = new LocalTransactionDataSource(
"jdbc:h2:mem:tutorial;DB_CLOSE_DELAY=-1", "sa", null);
transactionManager = new LocalTransactionManager(
dataSource.getLocalTransaction(getJdbcLogger()));
}
@Override
public Dialect getDialect() {
return dialect;
}
@Override
public DataSource getDataSource() {
return dataSource;
}
@Override
public TransactionManager getTransactionManager() {
return transactionManager;
}
public static DbConfig singleton() {
return CONFIG;
}
}
使用法
コード例では次の DAO インターフェイスを使用します。
@Dao
public interface EmployeeDao {
@Sql("select /*%expand*/* from employee where id = /*id*/0")
@Select
Employee selectById(Integer id);
@Update
int update(Employee employee);
@Delete
int delete(Employee employee);
}
トランザクションの開始と終了
次の TransactionManager のメソッドのいずれかを使用してトランザクションを開始できます。
required
requiresNew
notSupported
ラムダ式を使用して、トランザクションで実行する処理を記述します。
TransactionManager tm = DbConfig.singleton().getTransactionManager();
EmployeeDao dao = new EmployeeDaoImpl(DbConfig.singleton());
tm.required(() -> {
Employee employee = dao.selectById(1);
employee.setName("hoge");
employee.setJobType(JobType.PRESIDENT);
dao.update(employee);
});
ラムダ式が正常に終了すると、トランザクションはコミットされます。ラムダ式が例外をスローした場合、トランザクションはロールバックされます。
明示的なロールバック
例外をスローする以外に、 setRollbackOnly メソッドを使用してトランザクションをロールバックすることもできます。
TransactionManager tm = DbConfig.singleton().getTransactionManager();
EmployeeDao dao = new EmployeeDaoImpl(DbConfig.singleton());
tm.required(() -> {
Employee employee = dao.selectById(1);
employee.setName("hoge");
employee.setJobType(JobType.PRESIDENT);
dao.update(employee);
// Mark as rollback
tm.setRollbackOnly();
});
セーブポイント
セーブポイントを使用すると、トランザクション内の特定の変更をキャンセルできます。
TransactionManager tm = DbConfig.singleton().getTransactionManager();
EmployeeDao dao = new EmployeeDaoImpl(DbConfig.singleton());
tm.required(() -> {
// Search and update
Employee employee = dao.selectById(1);
employee.setName("hoge");
dao.update(employee);
// Create a savepoint
tm.setSavepoint("beforeDelete");
// Delete
dao.delete(employee);
// Rollback to the savepoint (cancel the deletion above)
tm.rollback("beforeDelete");
});