2012-05-17 36 views
5

Tengo un problema que se genera al azar (una vez entre la milésima de llamadas). El error ORA-01722: el número no válido se genera de forma aleatoria al ejecutar la actualización sql en una base de datos de Oracle preparada. Los detalles de casos son como a continuación:No puedo entender la razón detrás de ORA-01722: número inválido

try { 
     connection = getConnection(); 
     statement = connection.prepareStatement(sql); 
     for (int i = 0; i < params.length; i++) { 
      if (params[i] instanceof Date) { 
       statement.setTimestamp(i + 1, new Timestamp(((Date) params[i]).getTime())); 
      } else if (params[i] instanceof java.util.Date) { 
       statement.setTimestamp(i + 1, new Timestamp(((java.util.Date) params[i]).getTime())); 
      } else { 
       statement.setObject(i + 1, params[i]); 
      } 
      paramsBuilder.append(": " + params[i]); 
     } 
     if (logger.isInfoEnabled()) { 
      logger.info("Query String [" + sql + "] [" + paramsBuilder + "]"); 
      logger.info("Query Parameters [" + paramsBuilder + "]"); 
     } 
     result = statement.executeUpdate(); 
     if (logger.isInfoEnabled()) { 
      logger.info(result + " rows affected"); 
     } 
    } catch (SQLException e) { 
     if (logger.isInfoEnabled()) { 
      String message = "Failed to execute SQL statment [" + sql + "] with parameters [" + paramsBuilder + "]"; 
      logger.error(message, e); 
     } 
     throw new DAOException(e); 
    } 

y el valor en el registro es así:

Failed to execute SQL statment [update CUSTOMER_CASE set no_of_ptp=?, no_of_unreached=?,collector_name=? , last_case_status_history_id=?, current_handler=?, handling_start_time=?,due_total_open_amount=?, payment_due_invoice_id =? where id=?] with parameters [: 0: 0: auto: 5470508: null: null: 0.0: 23410984: 2476739] java.sql.SQLException: ORA-01722: invalid number 

mediante el trazado de los parámetros de consulta en DB todos los parámetros se transfieren correctamente a través del controlador JDBC excepto para el parámetro fue reemplazado por el valor "<C4>^X* U" (tenga en cuenta que este valor contiene el retorno de carro antes de "¡" u "!"). No sé por qué

+2

¿Cuál es el tipo de objeto que está intentando insertar? The toString() devuelve 23410984, pero ¿es un Integer, Long o BigDecimal? – Augusto

+0

¿Cuál es el alcance de 'statement' y' result'? –

+0

El tipo de objeto es largo y la columna de la base de datos es el número – user1017344

Respuesta

4

La razón principal es aproximadamente java.sql.SQLException: ORA-01722: invalid number.
puede ser el campo last_case_status_history_id tipo es el número, pero el parámetro es nulo

2

He intentado esto:

SELECT DUMP(23410984, 17) 
FROM dual; 

y obtuve esto:

Typ=2 Len=5: c4,^X,*,^J,U 

que es prácticamente lo mismo que lo que tiene. Tipo 2 es NUMBER tipo de datos.

documentación de Oracle dice que para el segundo parámetro de la función DUMP():

17 vuelve cada byte impresa como un personaje si y sólo si puede ser interpretado como un carácter imprimible en el juego de caracteres del compilador normalmente ASCII o EBCDIC. Algunos caracteres de control ASCII pueden imprimirse en la forma^X también. De lo contrario, el personaje se imprime en notación hexadecimal. Todos los parámetros de NLS son ignorados.

Parece que a veces el valor se transfiere no como el formato de byte interno de NUMBER sino como una cadena.

+1

Quizás debería ser más explícito para los valores que no sean de marca de tiempo, y usar 'setLong()'. –

2

Tuvimos un problema similar. Nuestro código de Java basado en hibernación emitió una declaración preparada para completar la información del usuario y una "razón para el cambio" para todas las operaciones de salvar mediante el uso de aspectJ.

En 3 entornos de bases de datos separados (Oracle 10G) esto funcionó sin problemas, pero en la base de datos de producción esto a veces falló con el error ORA-01722. Esto solo ocurre cuando la carga de la CPU en el servidor de la base de datos es cercana al 100%.

En otro foro encontré una sugerencia sobre no pasar objetos Largos pero haciendo unboxing explícitamente a una primitiva larga. Parece que el controlador jdbc o la base de datos en sí tiene problemas al hacer esto unboxing en alta carga (incluso si eso suena bastante loco). Se probaron varios controladores jdbc, como las versiones 1.4 y 1.6.

El código que a veces no era:

private void execute(final Long userId, final String rfc) { 
    Object[] args = new Object[]{ userId, rfc }; 
    getJdbcTemplate().update("call schema.package.setUserAndRFC(?,?)", args); 
} 

Ahora hemos cambiado el código para hacer un PreparedStatement explícita así:

private void execute(final Long userId, final String rfc) { 
    getJdbcTemplate().update(prepareStatement(userId.longValue(), rfc)); 
} 

private PreparedStatementCreator prepareStatement(final long userId, final String rfc) { 
    return new PreparedStatementCreator() { 
     @Override 
     public PreparedStatement createPreparedStatement(Connection con) throws SQLException { 
      PreparedStatement statement = con.prepareStatement("call schema.package.setUserAndRFC(?,?) "); 
      statement.setLong(1, userId); 
      statement.setString(2, rfc); 
      return statement; 
     } 
    }; 
} 

Este problema no ha sucedido desde entonces, incluso cuando el entorno se mantuvo lo mismo con el mismo software y alta carga en la base de datos.

He oído de un colega que uno de los DBA pudo ver en el registro que la declaración preparada fue aceptada por la base de datos, pero no se le asignó ninguna CPU. (Tiene sentido ya que todas las CPU estarían ocupadas con una carga tan alta.) Puede ser que simplemente se genere el error equivocado, se debe lanzar un error de "sobrecarga de base de datos" de algún tipo o algo así. Aún mejor sería nunca crear un error así de todos modos.

Supongo que es principalmente la carga de la base de datos sin embargo, no es nada inteligente dejar que la carga de la CPU alcance el 100% todo el tiempo.

0

java.sql.SQLException: ORA-01722: invalid number.

Estaba usando un UDF en la parte superior de la columna donde se espera un número y obtenía un valor diferente que no es un número. Entonces la operación falla lanzando una excepción de número inválido.

Cuestiones relacionadas