Pregunta

Esta es una versión específica de esta pregunta .
Quiero comprobar si estoy insertando una fila duplicada. ¿Debo verificarlo programáticamente en la capa de mi aplicación?

if (exists(obj))
{
    throw new DuplicateObjectException();
}
HibernateSessionFactory.getSession().save(obj);
¿

o debería detectar la excepción lanzada por la capa de la base de datos y activada cuando violo la contraintelencia?

try
{
    HibernateSessionFactory.getSession().save(obj);
}
catch(ConstraintViolationException e)
{
    throw new DuplicateObjectException();
}

EDITAR: en otras palabras: aunque la restricción está ahí para permanecer (de todos modos es un buen diseño de base de datos, y no puedo estar seguro de que mi aplicación sea la única que acceda a la tabla). confíe en la restricción y maneje la excepción que provocará su infracción, o ¿es mejor que compruebe?

EDIT2: Por supuesto que verifico + inserto dentro de una transacción, bloqueando la tabla para asegurar que ningún otro proceso esté escribiendo otro registro mientras tanto

¿Fue útil?

Solución

Primero, debe tener una clave principal o restricción única en la base de datos para hacer cumplir esta unicidad correctamente, sin duda.

Dado que existe la restricción, ¿de qué manera debería codificar en la aplicación? Mi preferencia sería probar el inserto y detectar las excepciones. Debido a que, presumiblemente, la mayoría de las inserciones se realizarán correctamente, solo algunas fallarán como duplicados (¡eso es lo que significa "excepción")! .

Además, es teóricamente posible que la verificación de existencia sea incorrecta de todos modos, si alguien más logra confirmar un registro con el mismo valor clave en el pequeño intervalo entre su verificación de existencia y su inserción. Luego, si no atrapa la excepción de la base de datos, creerá que la inserción tuvo éxito cuando en realidad no lo hizo.

Otros consejos

Usted verifica que el objeto existe únicamente en el código de la aplicación, y luego, una vez que está seguro de que no, guarda el objeto alegremente. Pero otro cliente concurrente podría insertar su propio objeto en el momento entre sus dos líneas de código. Por lo tanto, obtendría una excepción duplicada de todos modos, solo que esta vez no la atrapará.

Debe hacer el save () y capturar la excepción. De lo contrario, tiene una condición de carrera con otros clientes concurrentes que trabajan en la misma base de datos.

Debe capturar la excepción de la base de datos a menos que pueda garantizar que su aplicación es la única que inserta filas (y que siempre insertará filas) en su base de datos.

EDITAR: Es posible que haya entendido mal la pregunta, pero aún argumentaría que la opción B (HibernateSessionFactory lanza la excepción ConstraintException de la base de datos) es la mejor opción. Siempre hay una pequeña posibilidad de que otra aplicación pueda insertar algo en el lapso de tiempo entre su cheque y la llamada a la función real. Además, la única forma de verificar si hay una duplicidad es realizar una consulta adicional que sea solo una pérdida innecesaria de rendimiento.

Mi comprensión original de la pregunta era que en la opción A, la comprobación de duplicados se realizaría internamente (es decir, utilizando solo las estructuras de datos que el programa ya había creado, y sin consulta hasta el INSERT). Mi respuesta original fue en respuesta a este método.

En general, trato de evitar la codificación que se basa en errores que se lanzan porque hice algo mal. A veces, sin embargo, eso es todo lo que puedes hacer. En tu situación, creo que deberías revisar primero.

Esto se interrumpirá (permitiendo entradas duplicadas) si la restricción se elimina por alguna razón (generalmente, el trabajo de mantenimiento donde el DBA no lo vuelve a habilitar). Debe comprobar esta situación dentro de la aplicación.

Sin embargo, es un buen diseño de base de datos que la base de datos aplique la restricción (como bien ha señalado), ya que otros también pueden usar la base de datos. Como generalización, es mejor suponer que las aplicaciones y las bases de datos viven en una relación M: M; este será el caso casi todo el tiempo.

Las excepciones lanzadas por Hibernate (o cualquier componente ORM) tienden a ser difíciles de interpretar.

Si la excepción tiene suficiente información para que pueda generar un mensaje de error que realmente ayude al usuario, simplemente detecte la excepción, analícela y continúe.

Si la excepción no tiene suficiente información, entonces debe verificar la condición del error y generar un mensaje de error útil para el usuario de que está haciendo algo mal.

La pregunta es una de " ¿cuán opaca es la excepción " ;? Algunos son bastante opacos. Otros tienen lo suficiente como para analizar la cadena del mensaje y averiguar qué decir al usuario.

Una vez que hibernate arroja una excepción de la sesión, debe descartar la sesión (ver sección 11.2.3). Por lo tanto, si necesita verificar dups y continuar usando la misma sesión, entonces no tiene más remedio que verificar primero en la aplicación.

También hay una posibilidad con el código en el primer fragmento de código de que otro proceso podría insertar un registro que causaría que se lanzara la excepción duplicada entre el momento en que se verifica el registro duplicado y el momento en que realmente se inserta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top