我经常使用内存中的HSQL数据库作为测试数据库来编写数据库相关代码的单元测试。最近,我决定从1.8.1.3升级到2.2.9,以利用在2.x版本分支中添加的ROW_NUMBER()支持。
似乎在某种程度上,新版本比旧版本更严格。使用Hibernate(3.6.10)作为ORM,例如,我可能创建一个Configuration对象来创建first SessionFactory,然后使用该对象来填充测试数据,然后将Configurationto 对象用于被测试的类,这将创建它自己SessionFactory进行选择。使用hsqldb 1.8.1.3,没问题。对于2.2.9,select块位于hsqldb代码内部。以下是SSCCE对此进行说明:
Configuration
SessionFactory
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,我可以使用withTxtrue或false 运行此代码,这会很好。对于HSQLDB 2.2.9,withTx 必须将其设置为true ,否则线程将在.list()调用时被阻塞,并具有以下堆栈:
withTx
.list()
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
HSQLDB在1.8.1.3和2.2.9之间进行了哪些更改,需要此代码在事务中进行保存,我可以将其关闭吗?
HSQLDB 1.8.x使用READ UNCOMMITTED对已被其他事务添加或更改的行。
HSQLDB 1.8.x
READ UNCOMMITTED
HSQLDB 2.x使用READ COMMITTED(默认情况下)或SERIALIZABLE隔离级别。因此,事务必须在其更改可见之前提交。还有transaction model要考虑的。
HSQLDB 2.x
READ COMMITTED
SERIALIZABLE
transaction model
缺省值transaction model是LOCKS锁定被修改的表,直到提交事务为止。您可以使用MVCC model代替,它允许其他会话从表中读取并修改未修改的行。您可以将此模型与一起使用URL property。
LOCKS
MVCC model
URL property
config.setProperty(Environment.URL, "jdbc:hsqldb:mem:testDB;hsqldb.tx=mvcc");