「//fix this/」の記事インデックス

//fix this/ Javaコードの間違いをさがせ!


このシリーズは、あなたのコーディング・スキルを試すコーナーです。毎号オラクルのJavaエバンジェリストたちが、Javaコードに関する難問を出題し、正解と解説を掲載します。是非、毎号チャレンジして貴方のコーディング能力の向上にお役立て下さい。


第5回目 (Java Magazine 2012/Nov-Decからの出題)


1. 今回のテーマ 「JPA」

Java Persistence API(JPA)を使うようにJDBCコードを移植するにはトランザクションのロールバックに驚くほど異なった処理が必要になります。



2. コード

以下のコードを使って、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");}

その結果、コードの実行に失敗しました。



3.正しいのはどれ?

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");}
}


<< 第4回へ戻る I 第6回へ進む >>

「//fix this/」の記事インデックス