Domanda

Sto usando l'ibernazione 3 con c3p0 per un programma che estrae costantemente i dati da qualche fonte e li scrive in un database. Ora il problema è che il database potrebbe non essere disponibile per alcuni motivi (nel caso più semplice: l'ho semplicemente chiuso).

Se qualcosa sta per essere scritto nel database non dovrebbe esserci alcuna eccezione: la query dovrebbe attendere tutta l'eternità fino a quando il database non sarà nuovamente disponibile. Se non sbaglio questa è una delle cose che il pool di connessioni potrebbe fare per me: se c'è un problema con il db, prova a connetterti - nel peggiore dei casi per l'infinito.

Ma invece ottengo un'eccezione di pipe interrotta, a volte seguita da una connessione rifiutata e quindi l'eccezione viene passata al mio codice, il che non dovrebbe accadere.

Anche se rilevo l'eccezione, come potrei reinizializzare nuovamente l'ibernazione in modo pulito? (Finora senza c3p0 ho semplicemente costruito di nuovo la sessione factory, ma non sarei sorpreso se ciò potesse perdere connessioni (o è ok farlo?)).

Il database è l'edizione open source Virtuoso.

My hibernate.xml.cfg c3p0 config:

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
<property name="hibernate.c3p0.breakAfterAcquireFailure">false</property>
<property name="hibernate.c3p0.acquireRetryAttempts">-1</property>
<property name="hibernate.c3p0.acquireRetryDelay">30000</property>
<property name="hibernate.c3p0.automaticTestTable">my_test_table</property>

<property name="hibernate.c3p0.initialPoolSize">3</property>
<property name="hibernate.c3p0.minPoolSize">3</property>
<property name="hibernate.c3p0.maxPoolSize">10</property>

btw: la tabella di test è stata creata e ottengo tonnellate di output di debug, quindi sembra che in realtà legga la configurazione.

È stato utile?

Soluzione

Beh, sembra che BoneCP lo abbia effettivamente implementato. Può essere impostato per registrare la transazione e riprodurla in caso di errore della rete o del database:

http: // jolbox.com/bonecp/downloads/site/apidocs/com/jolbox/bonecp/BoneCPConfig.html#setTransactionRecoveryEnabled(boolean)

Altri suggerimenti

  

Se non sbaglio questa è una delle cose che il pool di connessioni potrebbe fare per me: se c'è un problema con il db, prova a connetterti - nel peggiore dei casi per l'infinito.

Ti sbagli. Un pool di connessioni è solo ... un pool di connessioni, contiene alcune connessioni fisiche già stabilite al database e viene utilizzato per evitare il sovraccarico di creare queste connessioni quando ne hai bisogno.

Detto questo, queste connessioni possono diventare obsolete (ad es. se si riavvia il database). Fortunatamente, la maggior parte dei pool di connessioni può essere configurata per verificare se una connessione è ancora valida e rinnovarla prima di distribuirle. c3p0 supporta questa funzione come documentato in Configurazione del test di connessione e sei in realtà già utilizzando una delle varie opzioni. Quindi le tue connessioni dovrebbero essere rinnovate al ritorno del database.

Ma non aspettarti che la tua applicazione venga magicamente sospesa quando il database si arresta, un pool non lo farà.

Grazie per la risposta. Sembra che non ho davvero capito l'ultimo paragrafo della sezione http://www.mchange.com/projects/c3p0/index.html# configuring_recovery

Perché all'inizio sembra che c3p0 possa farlo (rilevare connessioni non aggiornate e riprovare ad acquisire connessioni per tutta l'eternità senza mai gettare un'eccezione al codice dell'applicazione (a meno che ovviamente quando si tratti di un errore relativo all'istruzione sql e non al connessione), ma nell'ultimo paragrafo - che è scritto in modo piuttosto confuso - sembra che c3p0 non possa garantirlo al 100%.

Quindi la mia soluzione era quella di creare un piccolo wrapper per i metodi di cui avevo bisogno dall'interfaccia di connessione jdbc, che tentano di riconnettersi se una query fallisce a causa di un errore di connessione. Ovviamente è un po 'confuso, perché preferirei che i miei componenti usassero l'interfaccia di connessione standard invece della mia interfaccia, ma almeno ora funziona in modo pulito.

Stai dimenticando:

  • E le tue transazioni che sono state avviate?
  • Che dire di eventuali dichiarazioni preparate che sono già state inviate al DB?
  • etc

La tua applicazione dovrà quindi riavviare la transazione. L'unico modo possibile a cui riesco a pensare è che il pool di connessioni tenga traccia di ogni chiamata all'handle di connessione e riproduca quelle in caso di errore, ma ciò rallenterebbe notevolmente il pool di connessioni.

Nel caso di BoneCP ( http://jolbox.com ), il pool rileva che si è verificato un errore da intercettare prima l'eccezione generata dal driver JDBC e gestirla contrassegnando tale connessione come difettosa oppure ricreando l'intero pool di connessioni.

Modifica: ora viene gestito.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top