Sono abbastanza nuovo per JPA e voglio trovare le migliori pratiche quando si gestiscono eccezioni di persistenza da JPA per cose come dire, violazioni di vincoli univoci che possono essere indirizzati a dall'utente. Ci sono un sacco di esempi su come scrivere app JPA, ma quasi nulla su come gestire le eccezioni lanciate da loro. :/come gestire e analizzare le eccezioni di persistenza JPA per fornire un messaggio significativo all'utente
Per esempio la registrazione di un utente, la persona entra un indirizzo email che è già in uso attivo da parte del sistema e ottiene una violazione di vincolo:
try {
em.persist(credentials);
} catch (javax.persistence.PersistenceException ex) {
che produce questo errore quando si aggiunge un'email duplicato :
WARNING: SQL Error: 0, SQLState: 23505
SEVERE: ERROR: duplicate key value violates unique constraint "EMAIL_UQ_IDX"
Detail: Key (email)=([email protected]) already exists.
Come posso ottenere una risposta significativa all'utente? Ad esempio qualcosa come: Oops sembra che qualcuno stia già usando quell'indirizzo email, sei sicuro di non esserti registrato prima? C'è una funzione integrata per analizzarla o dovrò eseguire espressioni regex rispetto al messaggio di eccezione in una (possibilmente una serie di) istruzioni?
E che dire se è catturato sul livello aziendale ... quali sono le migliori pratiche per sollevarlo fino al livello di presentazione ... come ho detto prima, in modo che possa essere fornito un messaggio "carino" per utente.
Aggiunto per chiarezza: Solo così la gente sa, ho avuto, avere, e sto ancora guardando tutti i diversi tipi di eccezioni di persistenza, ed ecco alcune delle ricerche che ho fatto io didn' t includono con l'esempio "provare affermazione" ho incluso sopra:
try {
em.persist(credentials);
} catch (javax.persistence.PersistenceException ex) {
System.out.println("EXCEPTION CLASS NAME: " + ex.getClass().getName().toString());
System.out.println("THROWABLE CLASS NAME: " + ex.getCause().getClass().getName().toString());
Throwable th = ex.getCause();
System.out.println("THROWABLE INFO: " + th.getCause().toString());
Logger.getLogger(CredentialsControllerImpl.class
.getName()).log(Level.INFO, "Credentials Controller "
+ "persistence exception "
+ "EXCEPTION STRING: {0}", ex.toString());
Logger.getLogger(CredentialsControllerImpl.class
.getName()).log(Level.INFO, "Credentials Controller "
+ "persistence exception "
+ "THROWABLE MESSAGE: {0}", th.getMessage());
Logger.getLogger(CredentialsControllerImpl.class
.getName()).log(Level.INFO, "Credentials Controller "
+ "persistence exceptions "
+ "THROWABLE STRING: {0}", th.toString());
}
:)
eccezioni come
DataAccessException
sottoclassi di
DataAccessException
può l'annotazione @Version noi essere ed eliminare la condizione della gara? Come funzionerebbe? Avevo pensato di fare il check-up come suggerisci, ma le condizioni della gara mi preoccupavano e lo fanno ancora. Come dici tu, le possibilità sono basse; ma questo significa solo che accadrà anche se raramente, quindi deve ancora essere gestito. Ammetto che questo è uno dei rari casi d'uso in cui l'utente ha bisogno di essere coinvolto, soprattutto se si desidera consentire a un nome utente e al req'd indirizzo email entrambi di essere unici. FWIW, provengo dal mondo dei grandi volumi (100 delle transazioni K/DB di DB/sz), così divento ansioso sugli hit DB non necessari. :) – BillRInoltre, suppongo sia ovvio che si verrebbe a creare un'eccezione di persistenza acquisita nel livello aziendale fino al livello di presentazione. Quando accade un errore di vincolo indirizzabile da parte dell'utente, questo è (come concordiamo anche se raramente ... il che significa che succederà: D). O probabilmente in tutti i casi e il livello di presentazione decide cosa chiede all'utente di correggere e cosa renderà una pagina di errore piacevole, anche se frustrante (per l'utente). Grazie per l'input, a proposito. – BillR
La @Version servirebbe a qualsiasi scopo qui: entrambi i thread controllerebbero se esiste già un messaggio di posta elettronica, entrambi non lo troverebbero, ed entrambi proverebbero ad inserire. La condizione di competizione verrà risolta dal vincolo univoco nel database. In tal caso, si visualizza un messaggio di errore generico all'utente o si riprova automaticamente la transazione non riuscita. Il tentativo ha buone probabilità (soprattutto se si utilizza un piccolo ritardo prima) per scoprire che l'e-mail esiste e verrà visualizzato un messaggio di errore significativo per l'utente. –