2009-11-24 11 views
33

Ho bisogno di controllare se un'eccezione è causata da qualche problema di database. Ricevo un'eccezione e controllo se la causa contiene la stringa "ORA" e la restituisco (qualcosa come "ORA-00001"). Il problema qui è che l'eccezione che ricevo è annidata all'interno di altre eccezioni, quindi se non scopro se si tratta di un'eccezione di Oracle, devo verificare la causa di tale eccezione e così via. C'è un modo più pulito per fare questo? C'è un modo per conoscere la prima causa (l'eccezione nidificata profonda) di una determinata eccezione?Java - trova la prima causa di un'eccezione

mio codice attuale è simile al seguente:

private String getErrorOracle(Throwable e){ 
     final String ORACLE = "ORA"; 
     if (e.getCause() != null && e.getCause().toString().contains(ORACLE)){ 
      return e.getCause().toString(); 
     } else if(e.getCause() != null){ 
      return getErrorOracle(e.getCause()); 
     } else { 
      return null; 
     } 
    } 

risposta

14

Basta attraversare la catena di eccezione fino ad arrivare a un'eccezione senza causa, e poi basta tornare quel messaggio, se si desidera che l'ultimo.

La tua funzione otterrà solo la prima causa, se ce n'è una.

Si consiglia di cercare la prima causa nel pacchetto, poiché l'effettiva più profonda potrebbe essere un'eccezione di Oracle, che è utile, ma a meno che non si riesca a vedere dove si è creato il problema, si avrà un tempo di ripararlo.

+1

Grazie. Penso che andrò da questa parte allora. Devo farlo perché il cliente desidera mostrare alcuni messaggi specifici quando l'eccezione è causata da qualsiasi problema relativo al database. Quando ricevo l'eccezione non so se è stata causata dal database poiché la prima eccezione è annidata all'interno della catena delle eccezioni, quindi stavo cercando un modo per risolverlo. – Averroes

+1

ehm, il suo metodo è ricorsivo, quindi otterrà la causa alla radice. – Bozho

+0

@Bozho - Ha tre dichiarazioni if ​​con resi. Se lo avesse chiamato di nuovo, sarebbe ricorsivo, ma avrebbe bisogno di cambiare la sua logica, quindi uscirà. –

0

è possibile utilizzare getStackTrace() dalla classe Throwable. Questo ti darebbe la pila di StackTraceElements con cui lavorare. È possibile scorrere lo StackTraceElements [] per trovare la stringa "ORA".

Fammi sapere se hai bisogno di un esempio.

2

Penso che qualsiasi errore generato da Oracle verrà incluso in una SQLException (qualcuno mi corregga se non è corretto). Dopo aver effettuato l'accesso a SQLException dovresti essere in grado di chiamare

getErrorCode() Recupera il codice di eccezione specifico del fornitore per questo oggetto SQLException.

farmi sapere se questo funziona come non ho mai provato :-)

Karl

+0

Sì. Sembra che l'eccezione lanciata da Oracle estende SQLException. Per quanto riguarda getErrorCode(), questo sembra restituire un numero e credo che tu abbia ragione su questo. Lo controllerò domani al lavoro. Grazie. – Averroes

-1

Se l'eccezione gettata sta andando sempre essere di un tipo specifico, come OracleException, si può prendere solo quell'eccezione.

Ad esempio:

try { 

    ... 

} catch(OracleException oe) { 

    ... 

} 

Si dovrebbe applicare solo se ci sono eccezioni specifiche di Oracle che sono gettati. Non so molto su Oracle, quindi prima di tentare di farlo probabilmente vorrai scoprire se è quello che sta succedendo.

2

Si potrebbe migliorare il vostro codice di verifica di SQLException

import java.sql.SQLException; 

private static final String ORACLE = "ORA"; 

public String doHandle(Throwable t) { 
    if (t.getClass().isAssignableFrom(SQLException.class)) { 
    SQLException e = (SQLException) t; 
    int errCode = e.getErrorCode(); 
    String state = e.getSQLState(); 
    String msg = e.getMessage(); 
    if (msg.contains(ORACLE)) { 
     return msg; 
     } 
    } else { 
     if (t.getCause() != null) { 
      return this.doHandle(t.getCause()); 
      } 
     } 
    return ""; 
} 

Inoltre, penso che in Oracle "errCode" contiene il numero associato a ORA-nnnn

+2

Grazie. Questo mi aiuta molto a migliorare la funzione. Ho appena modificato "t.getClass(). IsAssignableFrom (SQLException.class)" a "t instaceof SQLException" perché il primo non è stato valutato true (l'eccezione che stavo testando era BatchUpdateException) – Averroes

3

Probabilmente un po 'eccessivo per il vostro uso, ma penso è più pulito (e riutilizzabile)

interface ThrowablePredicate { 
    boolean accept(Throwable t); 
} 

public OracleErrorThrowablePredicate implements ThrowablePredicate { 
    private static final ORA_ERR = "ORA"; 

    public boolean accept(Throwable t) { 
     return t.toString().contains(ORA_ERR); 
    } 
} 


public class CauseFinder { 

    private ThrowablePredicate predicate; 

    public CauseFinder(ThrowablePredicate predicate) { 
     this.predicate = predicate; 
    } 

    Throwable findCause(Throwable t) { 
     Throwable cause = t.getCause(); 

     return cause == null ? null 
     : predicate.accept(cause) ? cause : findCause(cause) 
    } 
} 


// Your method 
private String getErrorOracle(Throwable e){ 
    return new CauseFinder(new OracleErrorThrowablePredicate()).findCause(e); 
} 
80

nell'interesse di non reinventare la ruota, se si sta utilizzando Apache Commons Lang, poi guarda ExceptionUtils.getRootCause().

Vale la pena includere una libreria solo per questo? Forse no. Ma se lo hai già sul tuo classpath, è lì per te, e nota che fa alcune cose che un'implementazione "ingenua" potrebbe non fare (ad esempio gestire cicli nella catena della causa ... ugh!)

-1

il 28-01-2015, devo incapace di risolvere il mio problema con qualsiasi soluzione di cui sopra, quindi la mia raccomandazione è di usare:

e.getMessage().toString(); 

Ps: Io lo utilizzo su Android .

+0

.toString() è ridondante, oltre al fatto che ciò non fa ciò che è stato richiesto. – pqsk

Problemi correlati