TransactionRequiredExceptionエラー
1. 概要
このチュートリアルでは、TransactionRequiredExceptionエラーの原因とその解決方法を調べます。
2. TransactionRequiredException
このエラーは通常、トランザクションなしでデータベースを変更するデータベース操作を実行しようとしたときに発生します。
たとえば、トランザクションなしでレコードを更新しようとすると、次のようになります。
Query updateQuery
= session.createQuery("UPDATE Post p SET p.title = ?1, p.body = ?2 WHERE p.id = ?3");
updateQuery.setParameter(1, title);
updateQuery.setParameter(2, body);
updateQuery.setParameter(3, id);
updateQuery.executeUpdate();
次の行に沿ってメッセージを表示して例外を発生させます。
...
javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1586)
...
3. トランザクションの提供
明らかな解決策は、データベースを変更する操作をトランザクションでラップすることです。
Transaction txn = session.beginTransaction();
Query updateQuery
= session.createQuery("UPDATE Post p SET p.title = ?1, p.body = ?2 WHERE p.id = ?3");
updateQuery.setParameter(1, title);
updateQuery.setParameter(2, body);
updateQuery.setParameter(3, id);
updateQuery.executeUpdate();
txn.commit();
上記のコードスニペットでは、トランザクションを手動で開始してコミットします。 Spring Boot環境ではですが、@Transactionalアノテーションを使用することでこれを実現できます。
4. 春のトランザクションサポート
よりきめ細かい制御が必要な場合は、SpringのTransactionTemplateを使用できます。 これにより、プログラマーはメソッドのコード実行を続行する直前にオブジェクトの永続性をトリガーできます。
たとえば、電子メール通知を送信する前に投稿を更新するとします。
public void update() {
entityManager.createQuery("UPDATE Post p SET p.title = ?2, p.body = ?3 WHERE p.id = ?1")
// parameters
.executeUpdate();
sendEmail();
}
上記のメソッドに@Transactionalを適用すると、更新プロセスで例外が発生してもメールが送信される場合があります。これは、メソッドが終了し、に戻る直前にのみトランザクションがコミットされるためです。呼び出し側。
したがって、 TransactionTemplate 内で投稿を更新すると、操作がすぐにコミットされるため、このシナリオを防ぐことができます。
public void update() {
transactionTemplate.execute(transactionStatus -> {
entityManager.createQuery("UPDATE Post p SET p.title = ?2, p.body = ?3 WHERE p.id = ?1")
// parameters
.executeUpdate();
transactionStatus.flush();
return null;
});
sendEmail();
}
5. 結論
結論として、データベース操作をトランザクションでラップすることは一般的に良い習慣です。 データの破損を防ぐのに役立ちます。 完全なソースコードは、Githubでから入手できます。