2013-04-19 11 views
5

テストデータベースとしてインメモリHSQLデータベースを使用してデータベース依存コードのユニットテストを頻繁に書き込みます。最近、1.8.1.3から2.2.9にアップグレードし、2.xリリースブランチで追加されたROW_NUMBER()サポートを利用することに決めました。hsqldb 1.8.1.3上のHibernateベースコードのユニットテストhsqldb 2.2.9

何らかの形で新しいバージョンが古いバージョンよりも厳しいようです。 ORMとしてHibernate(3.6.10)を使用すると、最初にSessionFactoryを作成するためにConfigurationオブジェクトを作成し、それを使用してテストデータを生成した後、テスト対象のクラスにConfigurationを使用して、自分自身を作成し​​ますSessionFactory選択。 hsqldb 1.8.1.3では問題ありません。 2.2.9では、selectブロックはhsqldbコードの内部にあります。以下は、このことを証明するSSCCEです:

public void testTwoSessionFactories() throws Exception { 
    boolean withTx = false; 

    AnnotationConfiguration config = new AnnotationConfiguration().addAnnotatedClass(Entity.class); 
    config.setProperty("hibernate.hbm2ddl.auto", "create"); 
    config.setProperty(Environment.DIALECT, HSQLDialect.class.getName()); 
    config.setProperty(Environment.DRIVER, jdbcDriver.class.getName()); 
    config.setProperty(Environment.URL, "jdbc:hsqldb:mem:testDB"); 
    config.setProperty(Environment.USER, "SA"); 
    config.setProperty(Environment.PASS, ""); 

    SessionFactory sessionFactory1 = config.buildSessionFactory(); 
    Session session = sessionFactory1.openSession(); 

    Transaction tx = null; 
    if (withTx) 
     tx = session.beginTransaction(); 

    session.save(new Entity("one")); 

    if (withTx) 
     tx.commit(); 

    session.flush(); 
    session.close(); 

    config.setProperty("hibernate.hbm2ddl.auto", ""); 
    SessionFactory sessionFactory2 = config.buildSessionFactory(); 
    Session session2 = sessionFactory2.openSession(); 
    List entities = session2.createCriteria(Entity.class).list(); 
    session2.close(); 
} 

withTxブール値に注意してください。 HSQLDB 1.8.1.3では、このコードをwithTx trueまたはfalseで実行できます。これは問題ありません。

Unsafe.park(boolean, long) line: not available [native method] 
LockSupport.park(Object) line: not available  
CountDownLatch$Sync(AbstractQueuedSynchronizer).parkAndCheckInterrupt() line: not available 
CountDownLatch$Sync(AbstractQueuedSynchronizer).doAcquireSharedInterruptibly(int) line: not available 
CountDownLatch$Sync(AbstractQueuedSynchronizer).acquireSharedInterruptibly(int) line: not available 
CountDownLatch.await() line: not available 
CountUpDownLatch.await() line: not available  
Session.executeCompiledStatement(Statement, Object[]) line: not available 
Session.execute(Result) line: not available 
JDBCPreparedStatement.fetchResult() line: not available 
JDBCPreparedStatement.executeQuery() line: not available  
BatchingBatcher(AbstractBatcher).getResultSet(PreparedStatement) line: 208 
CriteriaLoader(Loader).getResultSet(PreparedStatement, boolean, boolean, RowSelection, SessionImplementor) line: 1953 
CriteriaLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean) line: 802 
CriteriaLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean) line: 274 
CriteriaLoader(Loader).doList(SessionImplementor, QueryParameters) line: 2542 
CriteriaLoader(Loader).listIgnoreQueryCache(SessionImplementor, QueryParameters) line: 2276 
CriteriaLoader(Loader).list(SessionImplementor, QueryParameters, Set, Type[]) line: 2271  
CriteriaLoader.list(SessionImplementor) line: 119 
SessionImpl.list(CriteriaImpl) line: 1716 
CriteriaImpl.list() line: 347 
EntityTest.testTwoSessionFactories() line: 46 

必要と1.8.1.3と2.2.9の間でHSQLDBで何が変わった:HSQLDB 2.2.9では、withTxは、そうでない場合、スレッドは、以下のスタックと.list()呼び出しでブロックされる、真に設定する必要があります。このコードは、トランザクション内で保存を行うために、私はそれをオフにすることができますか?

+0

HSQLDBを開発している人に質問してください。 –

+0

すべてのデータベースのやりとりは、トランザクション内で実行する必要があります。これが、Hibernateのドキュメントが推奨するものです。私はバグを修正し、常にトランザクションを使用するようにします。また、なぜ2つの異なるセッションファクトリを使用していますか?それをする理由はありません。セッションファクトリは、一度作成しなければならない重量のあるオブジェクトです。クリアユニットテストの場合+1。 –

+0

@JBNizet Re:プロダクションコードのトランザクション私はいつもそうしていますが、テストセットアップコードでは、テストに混乱を招くだけだと思っています。それほど悪くない私はそれを変更することはできません! – sharakan

答えて

8

HSQLDB 1.8.xは、別のトランザクションによって追加または変更された行に対してREAD UNCOMMITTEDを使用します。

HSQLDB 2.xは、READ COMMITTED(デフォルト)またはSERIALIZABLEアイソレーションレベルを使用します。したがって、トランザクションは変更内容が表示される前にコミットする必要があります。考慮するtransaction modelもあります。

デフォルトのtransaction modelは、トランザクションがコミットされるまで変更されるテーブルをロックするLOCKSです。 MVCC modelを代わりに使用すると、他のセッションで表を読み取り、変更されていない行を変更することができます。このモデルはURL propertyで使用できます。

config.setProperty(Environment.URL, "jdbc:hsqldb:mem:testDB;hsqldb.tx=mvcc"); 
+0

それはそれのように聞こえる、私はそれをチェックアウトします。接続プールレベルでREAD UNCOMMITTEDに変更できるようにプロパティを変更する方法はありますか? – sharakan

+0

READ UNCOMMITTEDは新しいバージョンではサポートされていません。 – fredt

+0

私は、彼らが[docs](http://hsqldb.org/doc/guide/sessions-chapt.html#snc_tx_tx_cc)で話している汚れた読書の「機能」に頼っていました。テストで明示的なトランザクションを使用するように変更します。私に方法を示してくれてありがとう! – sharakan