2016-12-09 8 views
0

私の問題は、JPA/HibernateはentityManager.getTransaction()の呼び出しのためを返すということです。のisActive()私は明示的にしませんでした場合でも、トランザクションを開始します(下記のコードを参照)。はなぜJPA/Hibernateのトランザクションがアクティブである1明示的

ここで問題となるのは、データベースから何かを読みたいということです。このシナリオでは、永続化されたオブジェクトが実際のコードに適合しなくなり、再計算が必要であることを示しているためです。代わりに、すぐ下にはnullコードを返す、次の例外がスローされます:これは私を示し

Transaction rollback failed. 
org.hibernate.TransactionException: Unable to rollback against JDBC Connection 

、私は私のコードで起動しなかったトランザクションのどこかにあったに違いありません。上記のコードでは、最終的にブロックする

final EntityManager entityManager = Persistence.createEntityManagerFactory("test").createEntityManager(); 

try { 
    final TypedQuery<Test> query = entityManager.createQuery("SELECT t FROM test t", Test.class); 

    return query.getResultList(); 

} catch (final PersistenceException e) { 
    if (e.getCause() instanceof SerializationException) { 
     LOG.debug("Implementation changed meanwhile. That's ok - we return null."); 
     return null; 
    } 
    throw e; 

} finally { 
    EntityManagerCloser.closeEntityManager(entityManager); 
} 

され、EntityManagerCloserは、次のようになります

public final class EntityManagerCloser { 
    private static final Logger LOG = LoggerFactory.getLogger(EntityManagerCloser.class); 

    public static void closeEntityManager(EntityManager entityManager) { 
     if (entityManager.getTransaction().isActive()) { 
      try { 
       entityManager.getTransaction().rollback(); 
      } catch (PersistenceException | IllegalStateException e) { 
       LOG.error("Transaction rollback failed.", e); 
      } 
     } 
     if (entityManager.isOpen()) { 
      try { 
       entityManager.close(); 
      } catch (IllegalStateException e) { 
       LOG.error("Closing entity manager failed.", e); 
      } 
     }  
    } 
} 

Hibernate docsは「常にでも、読み取り専用操作のために、明確なトランザクション境界を使用」と言います。だから私は本当に挿入する必要があります

entityManager.getTransaction().begin(); 
.... 
<do read here> 
.... 
entityManager.getTransaction().commit(); 

私はデータベース上で行うすべての読み取り操作の周り?

ロールバックトランザクションブロックなしで読み取り専用操作用の別のcloseEntityManagerメソッドを実装できましたが、なぜトランザクションがあるのか​​を理解したいと思います。助けてくれてありがとう!

答えて

0

ジョバンのおかげで、私はすぐに私の問題への解決策を見つけた:

私はentityManager.getTransaction().isActive()を呼び出す前に、私のcloseEntityManager方法でentityManager.isJoinedToTransaction()をコールする必要があると思います。

これにより、明示的にtransaction.begin()を呼び出さなかったため、後でロールバックできないEntityManagerCloserが独自のトランザクションを開始できなくなります。

+0

あなたはこのhttp://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/transaction/support/TransactionSynchronizationManager.html#isActualTransactionActive() – karelss

+0

を使用してトランザクションを確認できますが、悲しいことですこのプロジェクトではSpringは使用できません。 – GreenTurtle

1

entityManager.getTransaction();を呼び出すと、新しいトランザクションオブジェクトが作成されるという問題があります。したがって、以下に示すように、トランザクション参照を変数に保存する方が良いです。

Transaction txn = entityManager.getTransaction(); 

if (txn.isActive()) { 
    try { 
    txn.rollback(); 
    } catch (PersistenceException | IllegalStateException e) { 
     LOG.error("Transaction rollback failed.", e); 
     } 
} 
+0

entityManager.getTransaction()を呼び出すと、トランザクションオブジェクトがまったく必要ないため、あなたの答えが私の質問に直接的な解決策ではなかったとしても、トランザクションが既に開始されていることに感謝します。 – GreenTurtle

関連する問題