2010-05-23 24 views
13

Básicamente tengo el esquema a continuación y estoy insertando registros si no existen. Sin embargo, cuando se trata de insertar un duplicado, arroja un error como era de esperar. Mi pregunta es si existe una manera fácil de hacer que Hibernate simplemente ignore las inserciones que de hecho insertarían duplicados.Restricción de hibernación ConstraintViolationException. ¿Hay alguna manera fácil de ignorar las entradas duplicadas?

CREATE TABLE IF NOT EXISTS `method` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `name` varchar(10) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `name` (`name`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; 


SEVERE: Duplicate entry 'GET' for key 'name' 
Exception in thread "pool-11-thread-4" org.hibernate.exception.ConstraintViolationException: could not insert: 

Respuesta

11

Mi pregunta es si hay una manera fácil de hacer que Hibernate para simplemente ignorar las inserciones que a su duplicados efecto de inserción?

¿Cómo es posible que Hibernate sepa que un registro tiene un valor no único sin insertar realmente el registro?

Si usted está haciendo inserciones de lote y no desea deshacer toda la transacción y desechar la sesión en caso de una ConstraintViolationException (eso es lo que debe hacer, en teoría, después de una excepción, consulte this thread y esto previous answer), mi sugerencia sería usar la API StatelessSession y atrapar el ConstraintViolationException.

+0

Eso es todo. The StatelessSession está haciendo el trabajo. – Johanna

1

Al igual que Pascal dijo, Hibernate no sabrá si es un duplicado hasta que realmente se haya insertado.

Me encontré con una situación similar antes; varios hilos hacían inserciones en el DB, pero algunos de ellos serían duplicados. Todo lo que hice fue atrapar y recuperar con gracia cuando se arrojó una de esas excepciones.

6

Hibernate no puede hacer esto. Sin embargo, puedes hacerlo tú mismo. Básicamente, hay dos opciones:

  1. Compruebe si hay duplicados antes de insertar; o
  2. Capture la excepción ConstraintViolationException y luego asegúrese de que la infracción se deba a un duplicado (ya que puede haber otras razones, como campos nulos).

El primero tiene la desventaja de que está buscando duplicados en cada inserción cuando la probabilidad de que realmente haya un duplicado puede ser baja. Este último será más rápido para el caso habitual en el que no se producen duplicados, pero tiene la desventaja de que debe comprobar los duplicados después de la cara. Cuando se lanza una excepción de restricción de restricción, invalida la sesión actual; esto significa que deberá enjuagar antes de realizar una búsqueda de un duplicado.

La comprobación de los duplicados antes del inserto es probablemente el enfoque más limpio, a menos que exista un problema importante de rendimiento del que deba preocuparse. Asegúrese de hacer la búsqueda e insertar en una transacción para asegurarse de que alguien no agregue un duplicado entre la búsqueda y la inserción; de lo contrario, obtendrá una excepción ConstraintViolationException.

1

En lugar de utilizar createQuery() en hibernación, use createSQLQuery() y pruebe una consulta como "REEMPLAZAR EN el método (id) VALUES (123);"

1

Usted puede tratar de capturar la excepción org.hibernate.exception.ConstraintViolationException y tragar la excepción en su código

Por ejemplo:

try { 
    sessionFactory.getCurrentSession().saveOrUpdate(entity); 
} catch (ConstraintViolationException e) { 
    // Ignore the exception here by doing nothing 
} 
0

incluso si se captura la excepción, puede haber otros problemas

try{ 
     session.save(O); 
     session.getTransaction().commit(); 
    }catch (HibernateException e) { 
     System.out.println("you are carched ¤#%SD¤") ; 
    } 
0

Puede usar la anotación @SqlInsert en su entidad, para cambiar los usos de hibernación de sql para hacer una inserción en la base de datos, hibernate actualmente debe estar usando esta declaración

insert into method(name, id) values (?,?) 

Si está utilizando MySQL, puede utilizar la instrucción @SqlInsert cambiar el SQL inserción mediante inserción ignoran comunicado MySQL

@SQLInsert(sql = "insert ignore into method(name, id) values (?,?)") 

Sin embargo, usted debe obtener los sqls de inserción en activar el modo SQL espectáculo en hibernación, ya que el orden de las columnas se genera a través de alguna lógica, y sus documentos sugieren de esta manera.

Cuestiones relacionadas