Ich habe eine allgemeine Java-Methode mit der folgenden Methodensignatur:
private static ResultSet runSQLResultSet(String sql, Object... queryParams)
Es öffnet eine Verbindung, erstellt eine PreparedStatement
mit der SQL-Anweisung und den Parametern im queryParams
Array variabler Länge, führt sie aus, speichert das ResultSet
(in a CachedRowSetImpl
) zwischen, schließt die Verbindung und gibt die zwischengespeicherte Ergebnismenge zurück.
Ich habe Ausnahmebehandlung in der Methode, die Fehler protokolliert. Ich protokolliere die SQL-Anweisung als Teil des Protokolls, da sie beim Debuggen sehr hilfreich ist. Mein Problem ist, dass die Protokollierung der String-Variablen sql
die Template-Anweisung mit? S anstelle der tatsächlichen Werte protokolliert. Ich möchte die tatsächliche Anweisung protokollieren, die ausgeführt wurde (oder versucht wurde, ausgeführt zu werden).
Also ... Gibt es eine Möglichkeit, die tatsächliche SQL-Anweisung abzurufen, die von a ausgeführt wird PreparedStatement
? ( Ohne es selbst zu erstellen. Wenn ich keinen Weg finde, auf PreparedStatement's
SQL zuzugreifen , werde ich es wahrscheinlich selbst in meinem catch
es erstellen.)
quelle
Antworten:
Bei vorbereiteten Anweisungen gibt es keine "SQL-Abfrage":
Es gibt jedoch keine Neukonstruktion einer tatsächlichen echten SQL-Abfrage - weder auf der Java-Seite noch auf der Datenbankseite.
Es gibt also keine Möglichkeit, die SQL der vorbereiteten Anweisung abzurufen, da es keine solche SQL gibt.
Für Debugging-Zwecke sind die Lösungen entweder:
quelle
Es ist nirgends im JDBC-API-Vertrag definiert, aber wenn Sie Glück haben, kann der betreffende JDBC-Treiber die vollständige SQL durch einfaches Aufrufen zurückgeben
PreparedStatement#toString()
. DhMindestens MySQL 5.x- und PostgreSQL 8.x-JDBC-Treiber unterstützen dies. Die meisten anderen JDBC-Treiber unterstützen dies jedoch nicht. Wenn Sie eine solche haben, verwenden Sie am besten Log4jdbc oder P6Spy .
Alternativ können Sie auch eine generische Funktion schreiben, die a
Connection
, eine SQL-Zeichenfolge und die Anweisungswerte verwendet undPreparedStatement
nach der Protokollierung der SQL-Zeichenfolge und der Werte a zurückgibt . Kickoff-Beispiel:und benutze es als
Eine andere Alternative besteht darin, einen benutzerdefinierten
PreparedStatement
Code zu implementieren, der den RealPreparedStatement
bei der Konstruktion umschließt (dekoriert) und alle Methoden überschreibt, sodass er die Methoden des Real aufruftPreparedStatement
und die Werte in allensetXXX()
Methoden sammelt und die "tatsächliche" SQL-Zeichenfolge träge konstruiert, wann immer eine von DieexecuteXXX()
Methoden werden aufgerufen (eine ziemliche Arbeit, aber die meisten IDEs bieten Autogeneratoren für Dekorationsmethoden an, Eclipse tut dies). Verwenden Sie es schließlich einfach stattdessen. Das ist auch im Grunde das, was P6Spy und seine Kollegen bereits unter der Haube tun.quelle
logger.debug(sql + " " + Arrays.asList(values))
- ich suche nach einer Möglichkeit, die SQL-Anweisung mit den bereits integrierten Parametern zu protokollieren. Ohne mich selbst zu schleifen und die Fragezeichen zu ersetzen.PreparedStatement
jedes Mal erstellt. Wird das nicht so effizient sein, denn esPreparedStatement
geht darum, sie einmal zu erstellen und überall wiederzuverwenden?Ich verwende Java 8, JDBC-Treiber mit MySQL Connector Version 5.1.31.
Ich kann echte SQL-Zeichenfolge mit dieser Methode erhalten:
Es gibt also Folgendes zurück:
quelle
Apache Derby
?Wenn Sie die Abfrage sind die Ausführung und erwartet ein
ResultSet
(Sie in diesem Szenario sind, zumindest) , dann können Sie einfach anrufenResultSet
‚sgetStatement()
etwa so:Die Variable
executedQuery
enthält die Anweisung, mit der die erstellt wurdeResultSet
.Jetzt ist mir klar, dass diese Frage ziemlich alt ist, aber ich hoffe, das hilft jemandem.
quelle
Ich habe meine SQL aus PreparedStatement mit prepareStatement.toString () extrahiert. In meinem Fall gibt toString () einen String wie folgt zurück:
Jetzt habe ich eine Methode (Java 8) erstellt, die Regex verwendet, um sowohl Abfragen als auch Werte zu extrahieren und in die Map einzufügen:
Diese Methode gibt map zurück, wo wir Schlüssel-Wert-Paare haben:
Jetzt - wenn Sie Werte als Liste möchten, können Sie einfach verwenden:
Wenn Ihr prepareStatement.toString () anders ist als in meinem Fall, müssen Sie nur den regulären Ausdruck "anpassen".
quelle
Verwenden von PostgreSQL 9.6.x mit dem offiziellen Java-Treiber
42.2.4
:Zeigt die SQL mit der
?
bereits ersetzten, was ich gesucht habe. Habe gerade diese Antwort hinzugefügt, um den Postgres-Fall abzudecken.Ich hätte nie gedacht, dass es so einfach sein könnte.
quelle
Ich habe den folgenden Code zum Drucken von SQL aus PrepareStatement implementiert
quelle
Code-Snippet zum Konvertieren von SQL PreparedStaments mit der Liste der Argumente. Für mich geht das
quelle
Sehr spät :), aber Sie können die ursprüngliche SQL von einem OraclePreparedStatementWrapper von erhalten
quelle
oracle.jdbc.driver.OraclePreparedStatementWrapper
ist in oracle.jdbc.driver nicht öffentlich. Kann nicht von außerhalb des Pakets zugegriffen werden. Wie benutzt du diese Klasse?Wenn Sie MySQL verwenden, können Sie die Abfragen mithilfe des Abfrageprotokolls von MySQL protokollieren . Ich weiß nicht, ob andere Anbieter diese Funktion anbieten, aber die Chancen stehen gut, dass sie dies tun.
quelle
Einfach funktionieren:
Es ist auch gut für die vorbereitete Erklärung.
quelle
.toString()
mit ein paar zusätzlichen Zeilen, um unerfahrene Benutzer zu täuschen, und wurde bereits vor Ewigkeiten beantwortet.Ich verwende Oralce 11g und konnte das endgültige SQL nicht aus dem PreparedStatement abrufen. Nachdem ich die Antwort von @Pascal MARTIN gelesen habe, verstehe ich warum.
Ich habe gerade die Idee der Verwendung von PreparedStatement aufgegeben und einen einfachen Textformatierer verwendet, der meinen Anforderungen entsprach. Hier ist mein Beispiel:
Sie haben herausgefunden, dass sqlInParam dynamisch in einer (for, while) -Schleife erstellt werden kann. Ich habe es einfach gemacht, die MessageFormat-Klasse als Formatierungsvorlage für Zeichenfolgenvorlagen für die SQL-Abfrage zu verwenden.
quelle
((OraclePreparedStatementWrapper) myPreparedStatement).getOriginalSql()
Dazu benötigen Sie eine JDBC-Verbindung und / oder einen JDBC-Treiber, der die Protokollierung der SQL auf einer niedrigen Ebene unterstützt.
Schauen Sie sich log4jdbc an
quelle