Abbiamo un framework di test che utilizza JUnit, OpenEJB, Eclipselink e HSQLDB. Tutto ha funzionato fino ad ora, e testare il livello di servizio è un gioco da ragazzi. Ora, tuttavia, si verificano problemi durante l'importazione di massa su una tabella (utilizzando il livello di servizio, entitymanager) o, ad esempio, le entità persistenti in un elenco più volte in un metodo di servizio.Errore di violazione della chiave primaria HSQLDB nei test JUnit
QUESTA E 'LA PARTE DEGLI OBIETTIVI: I nostri test sembrano interrompersi solo se i test vengono eseguiti su una workstation sufficientemente veloce dalla riga di comando con Maven. Quando eseguo i test con Eclipse IDE, tutto va bene, ma a volte, casualmente, fallisce anche. Sospettiamo che possa avere qualcosa a che fare con la velocità con cui vengono eseguiti i test, per quanto strano possa sembrare. L'eccezione è abbastanza semplice perché in pratica ci dice che stiamo cercando di aggiungere un'entità con un ID già esistente. Abbiamo più volte controllato i nostri dati di test e il database hsqldb. Non ci sono righe preesistenti con ID che stiamo cercando di utilizzare. Ancora hsqldb lancia l'eccezione chiave primaria ad un certo punto. Dai nostri registri possiamo vedere che l'ID in conflitto non è sempre lo stesso, potrebbe essere 300015 o 300008.
Siamo alla fine del nostro spirito qui. Potrebbe avere qualcosa a che fare con le transazioni di HSQLDB o qualcos'altro che causa dati obsoleti?
Utilizziamo HSQLDB 2.2.8, Eclipselink 2.3.0 e OpenEJB 4.0.0-beta2.
La relazione che stiamo cercando di aggiungere entità è mappato come segue:
@OneToMany(mappedBy = "invoice", cascade = CascadeType.PERSIST)
private List<InvoiceBalance> getInvoiceBalanceHistory() {
if (invoiceBalanceHistory == null) {
this.invoiceBalanceHistory = new ArrayList<InvoiceBalance>();
}
return invoiceBalanceHistory;
}
L'eccezione principale è:
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:
ho cambiato la strategia di generazione della chiave primaria da GenerationType.AUTO (che sembra utilizzare la strategia TABLE per impostazione predefinita) a IDENTITY. Dopo questo, la nostra massa persiste sembra funzionare senza fallire. Non so ancora perché HSQLDB vada "fuori sincrono" con la strategia TABLE. Non vorrei cambiare le nostre entità jpa solo perché il nostro framework di test è bacato :)
Quale versione di HSQLDB stai utilizzando? JUnit impone un carico pesante di rollback della transazione sul database e probabilmente si sta verificando un bug o un compromesso di progettazione noto per mantenere HSQLDB veloce e piccolo. O forse una combinazione delle impostazioni del database e di come Eclipselink configura la tabella delle identità e la gestisce. È sempre una buona idea pubblicare i numeri di versione. –
Modificherò i numeri di versione nel post originale. Sto usando HSQLDB 2.2.8 Eclipselink 2.3.0 e OpenEJB 4.0.0-beta2. Anche l'entità non sta usando una colonna IDENTITÀ, invece la strategia è AUTO che penso stia usando la strategia TABLE su HSQLDB. –
Quanto ti preoccupi di trovare il problema rispetto a lavorare intorno ad esso? Passare da TABLE (o AUTO, che è TABLE per Eclipselink) a Sequence o IDENTITY probabilmente eliminerà il problema. Capire perché sta accadendo comporterà molti dolorosi scavi attraverso le impostazioni di transazione e isolamento e di rollback e bug nella cache e così via. –