Tengo un método Java general con la siguiente firma de método:
private static ResultSet runSQLResultSet(String sql, Object... queryParams)
Abre una conexión, construye PreparedStatement
usando la instrucción sql y los parámetros en la queryParams
matriz de longitud variable, la ejecuta, almacena ResultSet
en caché el (en a CachedRowSetImpl
), cierra la conexión y devuelve el conjunto de resultados en caché.
Tengo manejo de excepciones en el método que registra errores. Registro la instrucción sql como parte del registro, ya que es muy útil para la depuración. Mi problema es que el registro de la variable String sql
registra la declaración de la plantilla con? 'S en lugar de valores reales. Quiero registrar la declaración real que se ejecutó (o intentó ejecutar).
Entonces ... ¿Hay alguna forma de obtener la declaración SQL real que ejecutará un PreparedStatement
? ( Sin construirlo yo mismo. Si no puedo encontrar una manera de acceder al PreparedStatement's
SQL, probablemente terminaré construyéndolo yo mismo catch
).
fuente
Respuestas:
Usando declaraciones preparadas, no hay "consulta SQL":
Pero no hay una reconstrucción de una consulta SQL real real, ni en el lado de Java ni en el lado de la base de datos.
Por lo tanto, no hay forma de obtener el SQL de la declaración preparada, ya que no existe tal SQL.
Para fines de depuración, las soluciones son:
fuente
No está definido en ninguna parte en el contrato de la API JDBC, pero si tiene suerte, el controlador JDBC en cuestión puede devolver el SQL completo simplemente llamando
PreparedStatement#toString()
. Es decirAl menos los controladores JDBC MySQL 5.xy PostgreSQL 8.x lo admiten. Sin embargo, la mayoría de los otros controladores JDBC no lo admiten. Si tiene uno, entonces su mejor opción es usar Log4jdbc o P6Spy .
Alternativamente, también puede escribir una función genérica que tome una
Connection
, una cadena SQL y los valores de la instrucción y devuelva unPreparedStatement
después de registrar la cadena SQL y los valores. Ejemplo de inicio:y úsalo como
Otra alternativa es implementar una costumbre
PreparedStatement
que envuelva (decore) lo realPreparedStatement
en la construcción y anule todos los métodos para que llame a los métodos de lo realPreparedStatement
y recopile los valores en todos lossetXXX()
métodos y construya perezosamente la cadena SQL "real" cada vez que uno deexecuteXXX()
se llama a los métodos (todo un trabajo, pero la mayoría de los IDE proporcionan autogeneradores para métodos decoradores, Eclipse sí). Finalmente solo úsalo en su lugar. Eso también es básicamente lo que P6Spy y sus consortes ya hacen debajo de las campanas.fuente
logger.debug(sql + " " + Arrays.asList(values))
: estoy buscando una manera de registrar la instrucción sql con los parámetros ya integrados en ella. Sin repetirme y reemplazar los signos de interrogación.PreparedStatement
cada vez. ¿No será esa una manera no tan eficiente porque el objetivo principalPreparedStatement
es crearlos una vez y reutilizarlos en todas partes?Estoy usando Java 8, controlador JDBC con conector MySQL v. 5.1.31.
Puedo obtener una cadena SQL real usando este método:
Entonces devuelve algo como esto:
fuente
Apache Derby
?Si va a ejecutar la consulta y esperar un
ResultSet
(usted está en esta situación, por lo menos), entonces puede simplemente llamarResultSet
'sgetStatement()
de este modo:La variable
executedQuery
contendrá la declaración que se utilizó para crear elResultSet
.Ahora, me doy cuenta de que esta pregunta es bastante antigua, pero espero que esto ayude a alguien ...
fuente
Extraje mi sql de PreparedStatement usando prepareStatement.toString () En mi caso toString () devuelve String de esta manera:
Ahora he creado un método (Java 8), que utiliza expresiones regulares para extraer tanto la consulta como los valores y ponerlos en el mapa:
Este método devuelve el mapa donde tenemos pares clave-valor:
Ahora, si desea valores como lista, simplemente puede usar:
Si su prepareStatement.toString () es diferente que en mi caso, es solo cuestión de "ajustar" la expresión regular.
fuente
Usando PostgreSQL 9.6.x con el controlador oficial de Java
42.2.4
:Mostrará el SQL con el
?
ya reemplazado, que es lo que estaba buscando. Acabo de agregar esta respuesta para cubrir el caso de postgres.Nunca hubiera pensado que podría ser tan simple.
fuente
Implementé el siguiente código para imprimir SQL desde PrepareStatement
fuente
Fragmento de código para convertir SQL PreparedStaments con la lista de argumentos. Esto funciona para mi
fuente
Muy tarde :) pero puede obtener el SQL original de un OraclePreparedStatementWrapper por
fuente
oracle.jdbc.driver.OraclePreparedStatementWrapper
no es público en oracle.jdbc.driver. No se puede acceder desde un paquete externo. ¿Cómo estás usando esa clase?Si está utilizando MySQL, puede registrar las consultas utilizando el registro de consultas de MySQL . No sé si otros proveedores ofrecen esta función, pero es probable que lo hagan.
fuente
Simplemente funciona:
Está bien también para la declaración preparada.
fuente
.toString()
con un par de líneas adicionales para engañar a los usuarios inexpertos, y ya fue respondido hace años.Estoy usando Oralce 11g y no pude obtener el SQL final de PreparedStatement. Después de leer la respuesta de @Pascal MARTIN, entiendo por qué.
Simplemente abandoné la idea de usar PreparedStatement y usé un simple formateador de texto que se ajustaba a mis necesidades. Aquí está mi ejemplo:
Se da cuenta de que sqlInParam se puede construir dinámicamente en un bucle (for, while). Simplemente hice que sea sencillo llegar al punto de usar la clase MessageFormat para que sirva como formateador de plantillas de cadena para la consulta SQL.
fuente
((OraclePreparedStatementWrapper) myPreparedStatement).getOriginalSql()
Para hacer esto, necesita una conexión JDBC y / o un controlador que admita registrar el sql en un nivel bajo.
Echa un vistazo a log4jdbc
fuente