//fix this/ Javaコードの間違いをさがせ!
このシリーズは、あなたのコーディング・スキルを試すコーナーです。毎号オラクルのJavaエバンジェリストたちが、Javaコードに関する難問を出題し、正解と解説を掲載します。是非、毎号チャレンジして貴方のコーディング能力の向上にお役立て下さい。
Articles
Java
Java技術関連記事
Fix This
このシリーズは、あなたのコーディング・スキルを試すコーナーです。毎号オラクルのJavaエバンジェリストたちが、Javaコードに関する難問を出題し、正解と解説を掲載します。是非、毎号チャレンジして貴方のコーディング能力の向上にお役立て下さい。
Java Persistence API(JPA)を使うようにJDBCコードを移植するにはトランザクションのロールバックに驚くほど異なった処理が必要になります。
以下のコードを使って、JDBC経由でデータベースに接続するように設計されたプログラムがあります。
try {
statement.executeUpdate(sqlInsertStatement);
connection.commit(); log.info("Transaction committed");
} catch(SQLException e) {connection.rollback();
log.info("Transaction rolled back");}
数年後に、JPAを使うためにこのプログラムを以下のように再設計しました。
entityTransaction.begin();
try{
entityManager.createNativeQuery(sqlInsertStatement)
.executeUpdate();
entityTransaction.commit(); log.info("Transaction
committed");
} catch(Exception e) {entityTransaction.rollback();
log.info("Transaction rolled back");}
その結果、コードの実行に失敗しました。
1) entityTransaction.rollback()を呼び出す前に、entityTransaction.isActive()がtrueかをチェックする
2) RuntimeExceptionに対してentityTransaction.rollback()を呼び出す
3) RollbackExceptionに対してはentityTransaction.rollback()を呼び出さない
4) 上記のすべて
<ヒント>
JPAのそれぞれの例外の目的を確かめましょう。
正解は4)です。JPAのcommit()は処理に失敗した場合、データベース・ロールバックを実行してからトランザクションを終了します。正しいコードは次のようになります。
entityTransaction.begin();
try {entityManager.createNativeQuery(
sqlInsertStatement).executeUpdate();
entityTransaction.commit();}
catch(RollbackException e) {log.info(
"Transaction failed and was rolled back");}
catch(RuntimeException e) {
if (entityTransaction.isActive()) {entityTransaction
.rollback();log.error(
"Transaction ended abnormally and was rolled back");}
}