我经常使用内存中的HSQL数据库作为测试数据库编写数据库相关代码的单元测试。最近我决定从1.8.1.3升级到2.2.9,以利用2.x版本分支中添加的ROW_NUMBER()支持。
似乎在某种程度上,新版本比旧版本更严格。使用Hibernate(3.6.10)作为ORM,我可能会创建一个Configuration
对象来创建第一个SessionFactory
,用它来填充测试数据,然后使用Configuration
来正在测试的类,它创建了自己的SessionFactory
来进行选择。使用hsqldb 1.8.1.3,没问题。使用2.2.9,hsqldb代码中的select块。以下是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,并且它会没问题。使用HSQLDB 2.2.9时,withTx
必须设置为true ,否则线程将在.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之间发生了哪些变化需要此代码在事务中进行保存,我可以将其关闭吗?
答案 0 :(得分:10)
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");