2011-01-18 22 views
9

Tengo una aplicación que procesa un archivo muy grande y envía datos a una base de datos de Oracle (usando Java 6, Oracle 9).BatchUpdateException: el lote no terminará

En un ciclo, utilizo un PreparedStatement ps y creo todas las declaraciones SQL generadas con ps.addBatch().

Tengo una situación en la que se arroja un BatchUpdateException bue en algún lugar durante el ps.executeBatch(). En ese punto, el lote se detiene para ser ejecutado.

Me gustaría que la ejecución del lote continúe, para que pueda verificar las actualizaciones fallidas en un método processUpdateCounts(bue.getUpdateCounts()).

el Javadoc acerca de la clase BatchUpdateException dice:

Después de un comando en una actualización por lotes no se ejecuta correctamente y un BatchUpdateException se lanza, el conductor puede o no puede continuar a proceso de la comandos restantes en el lote .

¿Hay alguna manera de forzar la continuación o tengo que modificar mi programa para que ejecute la instrucción individualmente?

Respuesta

5

acaba de encontrar este enlace: JDBC Batch Update Problem

Al parecer, se dice que no existe

ninguna manera con Oracle JDBC LOTE para proceder después de la primera falta,

por lo que estoy recurriendo a enviar las inserciones una por una. Gracias

(disculpe por no verse mejor para encontrar el enlace anterior).

0

Dado que la especificación no parece obligarlo (como lo muestra claramente el Javadoc), cualquier continuación "forzada" tendría que hacerse en base al controlador. Una solución simple y compatible con el estándar sería verificar la matriz devuelta getUpdateCounts() y "volver a ejecutar" el lote para aquellas declaraciones que fallaron. Puede hacer que este enfoque sea un poco más sofisticado al establecer una lógica para el número de intentos.

Claro, esto parece un poco complicado (haciendo un seguimiento del "lote" agregado y luego verificando el resultado) pero funcionaría en todas las bases de datos y las implementaciones de controladores. Es sólo una idea ...

3

hay una solución que le permitiría usar la función de lote. En lugar de ejecutar una instrucción INSERT simple, puede ejecutar un bloque PL/SQL que se ocupará el error apropiadamente:

BEGIN 
    INSERT INTO your_table VALUES (?,?,...?); 
EXCEPTION 
    WHEN OTHERS THEN 
     /* deal with the error. For example, log the error id and error msg 
     so that you can list them after the batch */ 
     INSERT INTO error_table VALUES (?, sqlerrm); 
END 

El rendimiento debe estar a la par con la inserción por lotes (debería ser más rápido que la ejecución individual de la declaraciones). También puede llamar a un procedimiento almacenado en lugar de un bloque PL/SQL.

1

sí Oracle puede, ver aquí: http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14250/oci04sql.htm#sthref616

Sin embargo, no parece que esta funcionalidad se expone a JDBC, ni siquiera en las clases específicas de Oracle.

Debido al manejo de errores JDBC bastante inútil ("el controlador puede o no continuar"), siempre estoy estableciendo un punto de rescate antes del lote, y realizando una reversión a ese punto en caso de error. Esa es la única forma compatible con JDBC para establecer un estado conocido después de un error por lotes de Oracle, hasta donde yo sé.