gpt4 book ai didi

java - 在 hsqldb 1.8.1.3 之上基于 Hibernate 的代码的单元测试不再适用于 hsqldb 2.2.9

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:59:17 27 4
gpt4 key购买 nike

我经常使用内存中的 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 代码中的选择 block 。下面是一个 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 boolean 值。使用 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 之间有什么变化需要此代码在事务中进行保存,我可以将其关闭吗?

最佳答案

HSQLDB 1.8.x 使用 READ UNCOMMITTED 来处理已被另一个事务添加或更改的行。

HSQLDB 2.x 使用READ COMMITTED(默认)或SERIALIZABLE 隔离级别。因此,事务必须在其更改可见之前提交。还有 事务模型 需要考虑。

默认的事务模型LOCKS,它锁定一个被修改的表,直到事务被提交。您可以改用 MVCC 模型,它允许其他 session 从表中读取并修改未修改的行。您可以将此模型与 URL 属性 一起使用。

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

关于java - 在 hsqldb 1.8.1.3 之上基于 Hibernate 的代码的单元测试不再适用于 hsqldb 2.2.9,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16108643/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com