2010-09-08 13 views
7

Sto scrivendo un'applicazione che sincronizza le entità da un'origine dati di terze parti nel nostro schema, con una fase di trasformazione/mappatura intermedia. Sto usando Hibernate per rappresentare e persistere le entità nel nostro schema. Un problema che sto incontrando è che ho una chiave multi-colonna unica su uno dei miei tavoli. Il comportamento che vorrei vedere è analogo a un upsert: quando Hibernate va a persistere un'entità e rileva una violazione di un vincolo univoco, fa invece un aggiornamento. Stiamo usando MySQL, che fornisce una sintassi INSERT ... ON DUPLICATE KEY UPDATE, ma non sono sicuro di come o se Hibernate possa essere fatto per usarlo?Come imitare il comportamento di upsert usando Hibernate?

Suppongo che potrei sempre provare l'inserto e, se rilevo un'eccezione, faccio un aggiornamento, ma ciò sembra intrusivo e non ottimale. Qualche consiglio su un modo pulito per farlo?

risposta

4

Stiamo usando MySQL, che fornisce un INSERT ... ON DUPLICATE sintassi UPDATE chiave, ma io non sono sicuro di come o se Hibernate può essere fatta a fare uso di esso?

sembra che qualcuno did it sovrascrivendo la dichiarazione sql-insert usato da Hibernate per questa entità. Se non ti dispiace non essere portabile (e probabilmente usando una procedura memorizzata), dai un'occhiata.

Suppongo che potrei sempre provare l'inserto e, se rilevo un'eccezione, faccio un aggiornamento, ma ciò sembra intrusivo e non ottimale. Qualche consiglio su un modo pulito per farlo?

Un'altra opzione sarebbe quella di:

  1. effettuare una selezione sulla unica chiave
  2. se si trova un record, aggiornarlo
  3. se non trovate un record, crearla

Ma a meno che non si blocca l'intera tavolo (s) durante il processo, è possibile affrontare una certa condizione di competizione in un ambiente multi-threaded e distribuito e il passaggio 3 può potenzialmente fallire. Immaginate due thread simultanei:

Discussione 1:

  • cominciano trans
  • esegue una selezione su una chiave
  • non disponibili
  • creare un record
  • commettere

Thread 2:

  • cominciano trans
  • esegue una selezione sullo stesso tasto
  • non disponibili
  • creare un record
  • commettere (FAIL! perché thread 1 era più veloce e un record con la stessa chiave univoca ora esiste)

modo che avrebbe dovuto implementare un qualche tipo di meccanismo di riprovare in ogni caso (blocco l'intera tabella (s) non è una buona opzione IMO) .

3

La condizione di gara possono essere evitati "selezionare ... per l'aggiornamento"

+3

Se le partite selezionare nessuna riga, nessuna riga verranno bloccati da "per l'aggiornamento". La condizione della gara non è stata evitata. –

Problemi correlati