2009-11-24 20 views
33

Necesito comprobar si una excepción es causada por algún problema en la base de datos. Recibo una excepción y compruebo si su causa contiene la cadena "ORA" y la devuelvo (algo así como "ORA-00001"). El problema aquí es que la excepción que recibo está anidada dentro de otras excepciones, por lo que si no averiguo si se trata de una excepción de Oracle, debo verificar la causa de esa excepción y demás. ¿Hay alguna manera más clara de hacerlo? ¿Hay alguna forma de conocer la primera causa (la excepción anidada profunda) de una excepción dada?Java: busque la primera causa de una excepción

Mi código actual es el siguiente:

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; 
     } 
    } 

Respuesta

14

Sólo atraviesan la cadena excepción hasta llegar a una excepción, sin causa, y luego simplemente volver ese mensaje, si desea que el último.

Su función solo obtendrá la primera causa, si la hay.

Es posible que desee buscar la primera causa en su paquete, ya que la más profunda puede ser una excepción de oráculo, lo que es útil, pero a menos que pueda ver dónde creó el problema, tendrá una dificultad hora de arreglarlo.

+1

Gracias. Creo que iré de esta manera entonces. Tengo que hacer esto porque el cliente quiere mostrar algunos mensajes específicos cuando la excepción es causada por algún problema relacionado con la base de datos. Cuando recibo la excepción, no sé si fue causada por la base de datos, ya que la primera excepción está anidada dentro de la cadena de excepciones, así que estaba buscando una manera de resolver esto. – Averroes

+1

ehm, su método es recursivo, por lo tanto, obtendrá la causa raíz. – Bozho

+0

@Bozho - Tiene tres declaraciones if con devoluciones. Si lo llamara de nuevo, sería recursivo, pero necesitaría cambiar su lógica para que salga. –

0

puede usar el getStackTrace() de la clase Throwable. Esto le daría la pila de StackTraceElements para trabajar. Puede iterar a través de StackTraceElements [] para encontrar la cadena "ORA".

Avíseme si necesita un ejemplo.

2

Creo que cualquier error que arroje el oráculo se verá envuelto en una SQLException (alguien por favor corrígeme si está equivocado). Una vez que haya accedido a la excepción SQLException, debe poder llamar al

getErrorCode() Recupera el código de excepción específico del proveedor para este objeto SQLException.

Vamos a saber si esto funciona, ya que nunca he probado :-)

Karl

+0

Sí. Parece que la excepción lanzada por Oracle extiende SQLException. En cuanto a getErrorCode(), esto parece devolver un número y creo que tienes razón sobre esto. Lo veré mañana en el trabajo. Gracias. – Averroes

-1

Si la excepción siendo arrojada siempre va a ser de un tipo específico, como OracleException, se puede tomar solo esa excepción

Por ejemplo:

try { 

    ... 

} catch(OracleException oe) { 

    ... 

} 

Se aplicará únicamente si hay excepciones específicas de Oracle ser arrojado. No sé mucho sobre Oracle, así que antes de intentar esto, probablemente querrás saber si eso es lo que está sucediendo.

2

Se podría mejorar su código de comprobación de 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 ""; 
} 

Además, creo que en "de errCode" Oracle contiene el número asociado a ORA-nnnn

+2

Gracias. Esto me ayuda mucho a mejorar la función. Acabo de cambiar "t.getClass(). IsAssignableFrom (SQLException.class)" a "t instaceof SQLException" porque el primero no se estaba evaluando verdadero (La excepción que estaba probando fue BatchUpdateException) – Averroes

3

Probablemente un poco excesivo para su uso, pero creo es más limpio (y reutilizable)

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

En aras de no reinventar la rueda, si está usando Apache Commons Lang, a continuación, mira ExceptionUtils.getRootCause().

¿Vale la pena incluir una biblioteca solo para eso? Tal vez no. Pero si ya lo tiene en su classpath, está ahí para usted, y tenga en cuenta que hace algunas cosas que una implementación "ingenua" podría no hacer (por ejemplo, tratar con ciclos en la cadena de causas ... ugh!)

-1

el 28-01-2015, tengo incapaz de solucionar mi problema con cualquiera de la solución anterior, por lo que mi recomendación es usar:

e.getMessage().toString(); 

PD: lo estoy usando en android .

+0

.toString() es redundante además del hecho de que esto no hace lo que se solicitó. – pqsk

Cuestiones relacionadas