Wir haben ein Test-Framework mit JUnit, OpenEJB, Eclipselink und HSQLDB. Bis jetzt hat alles funktioniert, und das Testen der Service-Ebene ist ein Kinderspiel. Jetzt treten jedoch Probleme auf, wenn Massenimporte für eine Tabelle (unter Verwendung der Service-Schicht, des Entitäts-Managers) durchgeführt werden oder wenn beispielsweise Entitäten in einer Servicemethode mehrfach in einer Liste gespeichert werden.HSQLDB Primärschlüsselverletzung in JUnit Tests
Das ist der seltsame Teil: Unsere Tests scheinen nur zu brechen, wenn Tests auf einer schnell genug Workstation von der Befehlszeile mit Maven ausgeführt werden. Wenn ich die Tests über die Eclipse-IDE durchführe, ist alles in Ordnung, aber manchmal kommt es auch zufällig dazu. Wir vermuten, dass es etwas mit der Geschwindigkeit zu tun haben könnte, mit der die Tests durchgeführt werden, so seltsam es klingt. Die Ausnahme ist einfach genug, weil sie uns im Grunde sagt, dass wir versuchen, eine Entität mit einer bereits existierenden ID hinzuzufügen. Wir haben mehrmals unsere Testdaten und die hsqldb-Datenbank überprüft. Es gibt keine bereits vorhandenen Zeilen mit IDs, die wir verwenden möchten. Immer noch hsqldb löst die Primärschlüsselausnahme irgendwann aus. Aus unseren Protokollen können wir sehen, dass die in Konflikt stehende ID nicht immer die gleiche ist, es könnte 300015 oder 300008 sein.
Wir sind hier am Ende unserer Weisheit. Könnte es etwas mit HSQLDB-Transaktionen zu tun haben oder etwas anderes, das veraltete Daten verursacht?
Wir verwenden HSQLDB 2.2.8, Eclipselink 2.3.0 und OpenEJB 4.0.0-beta2.
Die Beziehung wir versuchen, Entitäten hinzufügen, wie folgt zugeordnet wird:
@OneToMany(mappedBy = "invoice", cascade = CascadeType.PERSIST)
private List<InvoiceBalance> getInvoiceBalanceHistory() {
if (invoiceBalanceHistory == null) {
this.invoiceBalanceHistory = new ArrayList<InvoiceBalance>();
}
return invoiceBalanceHistory;
}
Die Wurzel Ausnahme ist:
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation; SYS_PK_10492 table: INVOICEBALANCE
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(Unknown Source)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:831)
... 82 more
Caused by: org.hsqldb.HsqlException: integrity constraint violation: unique constraint or index violation; SYS_PK_10492 table: INVOICEBALANCE
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.Constraint.getException(Unknown Source)
at org.hsqldb.index.IndexAVLMemory.insert(Unknown Source)
at org.hsqldb.persist.RowStoreAVL.indexRow(Unknown Source)
at org.hsqldb.TransactionManager2PL.addInsertAction(Unknown Source)
at org.hsqldb.Session.addInsertAction(Unknown Source)
at org.hsqldb.Table.insertSingleRow(Unknown Source)
at org.hsqldb.StatementDML.insertSingleRow(Unknown Source)
at org.hsqldb.StatementInsert.getResult(Unknown Source)
at org.hsqldb.StatementDMQL.execute(Unknown Source)
at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
at org.hsqldb.Session.execute(Unknown Source)
EDIT:
änderte ich die primäre Strategie Schlüsselgenerierung von GenerationType.AUTO (das die TABLE-Strategie standardmäßig zu verwenden scheint) zu IDENTITY. Danach scheint unsere Masse bestehen geblieben zu sein. Ich weiß immer noch nicht, warum HSQLDB mit der TABLE-Strategie "nicht mehr synchron läuft". Ich würde unsere jpa-Entitäten nicht ändern wollen, nur weil unser Testframework fehlerhaft ist.
Welche Version von HSQLDB verwenden Sie? JUnit verursacht eine schwere Rollback-Last für die Datenbank und Sie werden wahrscheinlich in einen Bug oder einen bekannten technischen Kompromiss geraten, der dafür sorgt, dass die HSQLDB schnell und klein bleibt. Oder vielleicht eine Kombination Ihrer Datenbankeinstellungen und wie Eclipselink die Identitätstabelle konfiguriert und verwaltet. Es ist immer eine gute Idee, Versionsnummern zu veröffentlichen. –
Ich werde die Versionsnummern auf den ursprünglichen Beitrag bearbeiten. Ich verwende HSQLDB 2.2.8 Eclipselink 2.3.0 und OpenEJB 4.0.0-beta2. Außerdem verwendet die Entität keine IDENTITY-Spalte, stattdessen ist die Strategie AUTO, was meiner Meinung nach die TABLE-Strategie für HSQLDB verwendet. –
Wie sehr interessiert es Sie, das Problem zu finden, anstatt es zu umgehen? Der Wechsel von TABLE (oder AUTO, was TABLE für Eclipselink ist) zu Sequence oder IDENTITY wird das Problem wahrscheinlich beseitigen. Herauszufinden, warum es passiert, wird viele schmerzhafte Suche nach Transaktions- und Isolierungs- und Rollback-Einstellungen und das Zwischenspeichern von Fehlern beinhalten und so weiter. –