Tenemos un marco de prueba utilizando JUnit, OpenEJB, Eclipselink y HSQLDB. Todo ha funcionado bien hasta el momento, y probar el nivel de servicio es muy sencillo. Ahora, sin embargo, estamos teniendo problemas al hacer importaciones masivas en una tabla (utilizando el nivel de servicio, administrador de entidades) o, por ejemplo, las entidades persistentes a una lista varias veces en un método de servicio.HSQLDB error de violación de clave primaria en pruebas JUnit
ESTA ES LA PARTE EXTRAÑA: Nuestras pruebas parecen romperse solo si las pruebas se ejecutan en una estación de trabajo suficientemente rápida desde la línea de comandos con Maven. Cuando ejecuto las pruebas a través de Eclipse IDE, todo está bien, pero a veces, al azar, también falla. Sospechamos que podría tener algo que ver con la velocidad con la que se ejecutan las pruebas, por extraño que parezca. La excepción es bastante simple porque básicamente nos dice que estamos tratando de agregar una entidad con una identificación ya existente. Hemos comprobado varias veces nuestros datos de prueba y la base de datos hsqldb. No hay filas preexistentes con identificadores que estamos tratando de usar. Todavía hsqldb arroja la excepción de clave primaria en algún momento. De nuestros registros podemos ver que la ID en conflicto no es siempre la misma, podría ser 300015 o 300008.
Estamos en el último momento aquí. ¿Podría tener algo que ver con las transacciones de HSQLDB o alguna otra cosa que provoque datos obsoletos?
Estamos utilizando HSQLDB 2.2.8, Eclipselink 2.3.0 y OpenEJB 4.0.0-beta2.
La relación que estamos tratando de agregar entidades a se asigna de la siguiente manera:
@OneToMany(mappedBy = "invoice", cascade = CascadeType.PERSIST)
private List<InvoiceBalance> getInvoiceBalanceHistory() {
if (invoiceBalanceHistory == null) {
this.invoiceBalanceHistory = new ArrayList<InvoiceBalance>();
}
return invoiceBalanceHistory;
}
La excepción raíz es:
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:
me cambiaron la principal estrategia de generación de claves de GenerationType.AUTO (que parece usar la estrategia TABLE de forma predeterminada) para IDENTIDAD. Después de esto, nuestra masa persiste parece funcionar sin falta. Todavía no sé por qué HSQLDB "no está sincronizado" con la estrategia TABLE. No me gustaría cambiar nuestras entidades jpa solo porque nuestro framework de pruebas tiene errores :)
¿Qué versión de HSQLDB estás usando? JUnit impone una pesada carga de retrotracción de transacciones en la base de datos y es probable que se encuentre con un error o un compromiso de ingeniería conocido para mantener HSQLDB rápido y pequeño. O tal vez una combinación de su configuración de base de datos y cómo Eclipselink configura la tabla de identidad y la administra. Siempre es una buena idea publicar números de versión. –
Editaré los números de versión en la publicación original. Estoy utilizando HSQLDB 2.2.8 Eclipselink 2.3.0 y OpenEJB 4.0.0-beta2. Además, la Entidad no está utilizando una columna de IDENTIDAD, en cambio, la estrategia es AUTO, que creo que está utilizando la estrategia TABLE en HSQLDB. –
¿Cuánto te importa encontrar el problema en lugar de evitarlo? El cambio de TABLE (o AUTO, que es TABLE para Eclipselink) a Sequence o IDENTITY probablemente eliminará el problema. Entender por qué está sucediendo implicará una gran cantidad de excavaciones dolorosas a través de la transacción y el aislamiento y la configuración de deshacer y errores de almacenamiento en caché, y así sucesivamente. –