2016-08-27 7 views
1

Spring + Hibernate + SQLiteスタックのロールバックに失敗したトランザクションに問題があります。二つのフィールド(idとname) とPOJO - ここSpring + Hibernate + SQLiteトランザクション奇妙

は私の例の主要なクラス

  • 注釈アプリケーション構成http://pastebin.com/XbejGHft
  • TestBeanhttp://pastebin.com/3BSFy34p
  • 注文エンティティであり、

    は、それはいくつかの注文エンティティを作成し、持続する)方法TestBean.testMethod(で

    public void testMethod() { 
        entityManager.persist(createOrder("1")); 
        entityManager.persist(createOrder("2")); 
        entityManager.persist(createOrder("3")); 
        entityManager.createQuery("from Order").getResultList(); 
        entityManager.persist(createOrder("4")); 
        throw new RuntimeException("Managed"); 
    } 
    

    を検索します。 いくつかの作成の間に、データベースからデータを読み込みます。 最後に、RuntimeExceptionをスローしてメソッドの呼び出し中にエラーをシミュレートし、Spring to rollbackトランザクションを強制します。

    実行後、私はデータベースを開いて、最後に作成されたエンティティ(createOrder( "4"))とそれ以外のすべての(名前が "1"、 "2"、 "3"データベース。しかし、TestBeanは@Transactionalとしてマークされているので、あるトランザクションメソッドtestMethod()で作成された4つのエンティティをすべて削除する必要があります。

    SQLIteですべてのjournal_modeを試しましたが、ロールバックはまだ機能しませんでした。

    アイデア?

+0

各** em.persist()**呼び出しでHibernateが** JdbcIsolationDelegate#delegateWork **を呼び出すようです。同時に、メソッド** JdbcIsolationDelegate#delegateWork **呼び出し** Connection#commit **は、JPA/Hibernateフレームワーク内のすべてのトランザクション相互作用を破棄します – Joltd

答えて

0

私は長い間、問題の真の原因を見つけました。それは、アプリケーション内のすべてのエンティティの@GeneratedValueアノテーションの戦略タイプです。

デフォルトでは、注釈は戦略がAUTOであり、これはHibernateがID値を生成するためにターゲットデータベース(hibernate_sequence)内に独自のテーブルを使用することを意味します。 Hibernateは、別のトランザクション(hibernate_sequenceからの現在の値の選択)でクエリを呼び出します。この時点で問題に直面しました。

Hibernateが新しい接続を取得しようとするよりも汎用のマルチ接続データソースを使用しても、SQLiteにはアクティブな接続が1つしかない場合、「データベースファイルはロックされています」というエラーが発生します。 接続のクローズを防ぐSpringのSingleConnectionDataSourceを使用すると、Hibernateは既存の接続を再利用しますが、新しい別のトランザクションを作成します。新しいトランザクションは正常に完了しますが、新しいIDを要求した古いトランザクションは失敗します。

だから、解決策は非常に簡単です、ただすべてあなたのエンティティがだから

@GeneratedValue(strategy = GenerationType.IDENTITY) 

のように注釈を付けていることを確認し、この場合にはHibernateは基盤となるデータベースへのID値の生成を委譲します。

関連する問題