Pregunta

Una cosa que siempre ha sido una molestia es registrar los errores de SQL (JDBC) cuando tiene un PreparedStatement en lugar de la consulta en sí.

Siempre terminas con mensajes como:

2008-10-20 09:19:48,114 ERROR LoggingQueueConsumer-52 [Logger.error:168] Error 
executing SQL: [INSERT INTO private_rooms_bans (room_id, name, user_id, msisdn, 
nickname) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE room_id = ?, name = ?, 
user_id = ?, msisdn = ?, nickname = ?]

Por supuesto, podría escribir un método auxiliar para recuperar los valores y analizar / sustituir los signos de interrogación con valores reales (y probablemente seguiré ese camino si no obtengo un resultado de esta pregunta), pero solo quería para saber si este problema fue resuelto anteriormente por otra persona y / o si hay algún asistente genérico de registro que lo haría automáticamente para mí.

Editado después de algunas respuestas:

Las bibliotecas proporcionadas hasta ahora parecen ser adecuadas para registrar las declaraciones para la depuración, lo que sin duda es útil. Sin embargo, estoy buscando una forma de tomar una PreparedStatement en sí (no una subclase) y registrar su declaración SQL cada vez que se produce un error. No me gustaría implementar una aplicación de producción con una implementación alternativa de PreparedStatement.

Supongo que estoy buscando una clase de utilidad, no una especialización de PreparedStatement.

¡Gracias!

¿Fue útil?

Solución

Probé log4jdbc e hizo el trabajo por mí.

NOTA DE SEGURIDAD: A partir de hoy, agosto de 2011, los resultados registrados de una declaración preparada log4jdbc NO SON SEGUROS de ejecutar. Se pueden usar para el análisis, pero NUNCA se deben devolver a un DBMS.

Ejemplo de registro generado por logjdbc:

  

2010/08/12 16:30:56 jdbc.sqlonly   org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate (DelegatingPreparedStatement.java:105)   8. INSERTE EN UNA TABLA   (ID_FILE, CODE1, ID_G, ID_SEQUENCE, REF, NAME, BAR, DRINK_ID, AMOUNT, DESCRIPTION, STATUS, CODE2, REJECT_DESCR, ID_CUST_REJ)   VALORES   (2, '123', 1, '2', 'aa', 'awe', nulo, '0123', 4317.95, 'Rccc', '0', nulo, nulo, nulo)

La biblioteca es muy fácil de configurar:


Mi configuración con HSQLDB :

jdbc.url=jdbc:log4jdbc:hsqldb:mem:sample

Con Oracle :

jdbc.url=jdbc:log4jdbc:oracle:thin:@mybdd:1521:smt
jdbc.driverClass=net.sf.log4jdbc.DriverSpy

logback.xml:

<logger name="jdbc.sqlonly" level="DEBUG"/>

Lástima que no estaba en un repositorio de Maven, pero aún era útil.
Por lo que he intentado, si lo pones

Solo obtendrá las declaraciones por error, sin embargo, no sé si esta biblioteca tiene un impacto en el rendimiento.

Otros consejos

Esto es muy dependiente de la base de datos. Por ejemplo, entiendo que algunos controladores JDBC (por ejemplo, sybase, quizás ms-sql) manejan declaraciones preparadas al crear un procedimiento almacenado temporal en el servidor y luego invocar ese procedimiento con los argumentos proporcionados. Por lo tanto, el SQL completo nunca se pasa del cliente.

Como resultado, la API JDBC no expone la información que busca. Es posible que pueda convertir sus objetos de declaración en la implementación del controlador interno, pero probablemente no, su servidor de aplicaciones puede incluir las declaraciones en su propia implementación.

Creo que puede que tenga que morder la viñeta y escribir su propia clase que interpola los argumentos en el marcador de posición SQL. Esto será incómodo porque no puede solicitar a PreparedStatement los parámetros que se han establecido, por lo que deberá recordarlos en un objeto auxiliar antes de pasarlos a la instrucción.

Me parece que una de las bibliotecas de utilidades que envuelven los objetos de implementación de su controlador es la forma más práctica de hacer lo que está tratando de lograr, pero será desagradable de cualquier manera.

Use P6Spy : es Oracle, Mysql, JNDI, JMX, Spring y Maven amigables. Altamente configurable. Integración sencilla y de bajo nivel. Puede imprimir el stacktrace . Solo puede imprimir llamadas pesadas , basadas en tiempo.

  1. Si está utilizando MySQL, el estado PreparedStatement.toString () . Aunque los grupos de conexiones de terceros pueden romper esto.

  2. Subclase PreparedStatement para crear la cadena de consulta a medida que se agregan los parámetros. No hay forma de extraer el SQL de una declaración preparada, ya que utiliza un formulario binario compilado.

LoggedPreparedStatement parece prometedor, aunque no lo he probado.

Una ventaja de estos sobre un controlador proxy que registra todas las consultas es que puede modificar la cadena de consulta antes de iniciarla. Por ejemplo, en un entorno PCI es posible que desee enmascarar números de tarjeta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top