2010-05-23 9 views
13

Fondamentalmente ho lo schema seguente e sto inserendo i record se non esistono. Tuttavia quando si tratta di inserire un duplicato esso genera ed errore come mi aspetterei. La mia domanda è se esiste un modo semplice per fare in modo che Hibernate ignori gli inserti che in effetti inseriscono i duplicati?Vincolo di sospensione ConstraintViolationException. C'è un modo semplice per ignorare le voci duplicate?

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: 

risposta

11

La mia domanda è se c'è un modo semplice per fare Hibernate di ignorare solo inserti che a sua duplicati effetto insert?

In che modo Hibernate potrebbe sapere che un record ha un valore non univoco senza effettivamente inserire il record?

Se stai facendo inserti in batch e non si desidera eseguire il rollback l'intera transazione e scartare la sessione in caso di un ConstraintViolationException (che è quello che si dovrebbe fare, in teoria, dopo un'eccezione, vedi this thread e questo previous answer), il mio suggerimento sarebbe utilizzare l'API StatelessSession e prendere il ConstraintViolationException.

+0

Questo è tutto. The StatelessSession sta facendo il lavoro. – Johanna

1

Proprio come ha detto Pascal, Hibernate non saprà se è un duplicato fino a quando non è stato effettivamente avviato.

Ho riscontrato una situazione simile prima; diversi thread stavano facendo inserimenti nel DB, ma alcuni di questi sarebbero duplicati. Tutto ciò che ho fatto è stato catturare e recuperare con garbo quando una di quelle eccezioni è stata lanciata.

6

Hibernate non può farlo. Puoi comunque farlo da solo. Essenzialmente ci sono due opzioni:

  1. Verificare la presenza di duplicati prima dell'inserimento; oppure
  2. Catch the ConstraintViolationException e quindi assicurarsi che la violazione sia dovuta a un duplicato (poiché possono esserci altri motivi, come campi null).

Il primo ha lo svantaggio di controllare i duplicati su ogni inserto quando la probabilità che ci sia effettivamente un duplicato potrebbe essere bassa. Quest'ultimo sarà più veloce per il caso normale in cui non si verificano duplicati, ma ha lo svantaggio che è necessario verificare la presenza di duplicati dopo la faccia. Quando viene lanciata una ConstraintViolationException, invalida la sessione corrente; questo significa che dovrai eseguire il flush prima di fare una ricerca di un duplicato.

Controllare i duplicati prima di inserire è probabilmente l'approccio più pulito, a meno che non vi sia un problema di prestazioni di rilievo che è necessario preoccuparsi. Assicurati di eseguire la ricerca e inserisci una transazione per assicurarti che qualcuno non aggiunga un duplicato tra la ricerca e l'inserimento, altrimenti otterrai una ConstraintViolationException.

1

Invece di utilizzare createQuery() in ibernazione, utilizzare createSQLQuery() e provare una query come "REPLACE INTO method (id) VALUES (123);"

1

Si può provare a intercettare l'eccezione org.hibernate.exception.ConstraintViolationException e inghiottire l'eccezione nel codice

Ad esempio:

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

anche se si cattura l'eccezione, ci possono essere altri problemi

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

È possibile utilizzare l'annotazione @SqlInsert sull'entità, per modificare l'utilizzo di Hibernate sql per effettuare l'inserimento nel database, l'ibernazione attualmente deve utilizzare questa istruzione

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

Se si sta utilizzando MySQL, è possibile utilizzare l'istruzione @SqlInsert per cambiare lo SQL INSERT utilizzando inserto ignorare dichiarazione mysql

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

Tuttavia si dovrebbe ottenere i sqls inserimento abilitando la modalità SQL spettacolo in ibernazione, poiché l'ordine delle colonne viene generato tramite una logica e i loro documenti suggeriscono in questo modo.

Problemi correlati