2008-10-03 7 views
8

Esta es una versión específica de this question.
Quiero comprobar si estoy insertando una fila duplicada. Debería comprobar que mediante programación en mi capa de aplicación:Lógica: base de datos o aplicación/2 (comprobación de restricciones)

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

o debería atrapar la excepción lanzada por la capa de base de datos y activa cuando violo la contraint?

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

EDIT: En otras palabras: a pesar de la restricción es para permanecer allí (que es un buen diseño de base de datos de todos modos, y no puedo estar seguro que mi aplicación va a ser el único acceso a la tabla) he de confiar en la restricción y manejar la excepción, se levantará su violación, o será mejor que compruebe de todos modos?

Edit2: Por supuesto que consultar + insertar dentro de una transacción, el bloqueo de la mesa para asegurar ningún otro proceso está escribiendo un nuevo récord en el ínterin

Respuesta

7

En primer lugar, usted debe tener una clave principal o restricción única en la base de datos para hacer cumplir esta singularidad correctamente, no hay duda.

Dado que la restricción existe, ¿de qué manera debe codificar en la aplicación? Mi preferencia sería probar el inserto y atrapar las excepciones. Debido a que presumiblemente la mayoría de las inserciones tendrán éxito, solo unas pocas fallarán como duplicadas (¡eso es lo que implica "excepción"!): Es ineficiente realizar una comprobación existente antes de cada inserción, cuando la base de datos va a realizar su propia comprobación de restricciones de todos modos.

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

1

En general, trato de evitar la codificación que se basa en errores siendo arrojado porque hice algo mal. A veces, sin embargo, eso es todo lo que puedes hacer. En su situación, creo que debería verificar primero.

2

Debe detectar la excepción de la base de datos a menos que pueda garantizar que su aplicación sea la única que inserte filas (y alguna vez insertará filas) en su base de datos.

EDIT: que pueden tener entienden mal la pregunta, pero yo todavía argumentar que la opción B (HibernateSessionFactory lanza el 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 intervalo de tiempo entre su cheque y la llamada a la función real. Además, la única manera de verificar si un embaucador es realizar una consulta adicional es simplemente una pérdida de rendimiento innecesaria.

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

1

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

Sin embargo, es un buen diseño de la base de datos que la base de datos imponga la restricción (como ha señalado muy correctamente) ya que otros también pueden estar usando 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.

1

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

Si la excepción tiene suficiente información como para que pueda aparecer un mensaje de error que realmente ayude al usuario, simplemente capture la excepción, analícela y siga.

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

La pregunta es: "¿Qué tan opaca es la excepción"? Algunos son bastante opacos. Otros tienen suficiente para analizar la cadena del mensaje y descubrir qué decir al usuario.

0

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

También existe la posibilidad con el código en el primer fragmento de que otro proceso podría insertar un registro que provocaría la excepción duplicada entre el momento en que comprueba el registro duplicado y el tiempo que realmente se inserta.

2

Comprueba que el objeto existe únicamente en el código de la aplicación, y luego, una vez satisfecho de que no lo hace, guarde el objeto alegremente. Pero otro cliente simultáneo 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 de Duplicado de todos modos, solo que esta vez no la captaría.

Debe guardar() y atrapar la excepción. De lo contrario, tiene una condición de carrera con otros clientes simultáneos que trabajan en la misma base de datos.

Cuestiones relacionadas