Ich schreibe häufig Komponententests meiner Datenbank abhängigen Code mit einer In-Memory-HSQL-Datenbank als Test-Datenbank. Vor kurzem habe ich mich entschieden, von 1.8.1.3 auf 2.2.9 zu aktualisieren, um die ROW_NUMBER() - Unterstützung zu nutzen, die im 2.x-Versionszweig hinzugefügt wurde.Komponententests von Hibernate-basierten Code auf hsqldb 1.8.1.3 nicht mehr auf hsqldb 2.2.9
Es scheint, dass in gewisser Weise die neue Version strenger als die alte Version ist. Unter Verwendung von Hibernate (3.6.10) als ORM, könnte ich zum Beispiel ein Configuration
Objekt erstellen, um ein erstes SessionFactory
zu erstellen, das zum Auffüllen der Testdaten verwenden und dann das Configuration
für die zu testende Klasse verwenden, die ihr eigenes SessionFactory
erstellt eine Auswahl. Mit hsqldb 1.8.1.3, kein Problem. Mit 2.2.9 werden die Blöcke innerhalb des hsqldb-Codes ausgewählt. Nachfolgend finden Sie eine SSCCE dies demonstrieren:
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();
}
Notiere die withTx
boolean. Mit HSQLDB 1.8.1.3 kann ich diesen Code mit withTx
wahr oder falsch ausführen, und es wird in Ordnung sein. Mit HSQLDB 2.2.9, withTx
muss auf true gesetzt werden, da sonst der Faden in dem .list()
Aufruf mit dem folgenden Stapel blockiert wird:
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
Was in HSQLDB geändert zwischen 1.8.1.3 und 2.2.9, die erfordert, diesen Code, um das Speichern innerhalb einer Transaktion durchzuführen, und kann ich es ausschalten?
Vielleicht sollten Sie die Leute fragen, die HSQLDB entwickeln. –
Jede Datenbankinteraktion sollte trotzdem innerhalb einer Transaktion erfolgen. Das empfiehlt die Hibernate-Dokumentation. Ich würde den Fehler einfach beheben und sicherstellen, dass Sie immer Transaktionen verwenden. Warum verwenden Sie zwei verschiedene Sitzungsfactories? Es gibt keinen Grund, das zu tun. Eine Sitzungsfabrik ist ein schwergewichtiges Objekt, das ein für allemal erstellt werden sollte. +1 für den Test der eindeutigen Einheit. –
@JBNizet Re: Transaktionen, im Produktionscode tue ich das immer, aber im Test-Setup-Code bin ich lockerer, weil ich denke, dass es nur Krempel zum Test hinzufügt. Nicht so schlimm, dass ich es nicht ändern kann! – sharakan