J'ai une méthode Java générale avec la signature de méthode suivante:
private static ResultSet runSQLResultSet(String sql, Object... queryParams)
Il ouvre une connexion, construit une PreparedStatement
à l'aide de l'instruction sql et des paramètres du queryParams
tableau de longueur variable, l'exécute, met en cache le ResultSet
(dans a CachedRowSetImpl
), ferme la connexion et renvoie le jeu de résultats mis en cache.
J'ai la gestion des exceptions dans la méthode qui enregistre les erreurs. Je consigne l'instruction sql dans le cadre du journal car elle est très utile pour le débogage. Mon problème est que la journalisation de la variable String sql
enregistre l'instruction de modèle avec des? Au lieu des valeurs réelles. Je veux enregistrer l' instruction réelle qui a été exécutée (ou qui a tenté d'exécuter).
Alors ... Existe-t-il un moyen d'obtenir l'instruction SQL réelle qui sera exécutée par un PreparedStatement
? ( Sans le construire moi-même. Si je ne trouve pas un moyen d'accéder au PreparedStatement's
SQL, je finirai probablement par le construire moi-même dans mon catch
es.)
la source
Réponses:
En utilisant des instructions préparées, il n'y a pas de "requête SQL":
Mais il n'y a pas de reconstruction d'une vraie requête SQL réelle - ni du côté Java, ni du côté de la base de données.
Donc, il n'y a aucun moyen d'obtenir le SQL de l'instruction préparée - car il n'y a pas de tel SQL.
À des fins de débogage, les solutions sont les suivantes:
la source
Il n'est défini nulle part dans le contrat de l'API JDBC, mais si vous avez de la chance, le pilote JDBC en question peut renvoyer le SQL complet en appelant simplement
PreparedStatement#toString()
. C'est à direAu moins les pilotes JDBC MySQL 5.x et PostgreSQL 8.x le prennent en charge. Cependant, la plupart des autres pilotes JDBC ne le prennent pas en charge. Si vous en avez un, votre meilleur pari est d'utiliser Log4jdbc ou P6Spy .
Vous pouvez également écrire une fonction générique qui prend a
Connection
, une chaîne SQL et les valeurs de l'instruction et retourne aPreparedStatement
après avoir consigné la chaîne SQL et les valeurs. Exemple de lancement:et utilisez-le comme
Une autre alternative consiste à implémenter une personnalisation
PreparedStatement
qui enveloppe (décore) le réelPreparedStatement
lors de la construction et remplace toutes les méthodes afin d'appeler les méthodes du réelPreparedStatement
et de collecter les valeurs dans toutes lessetXXX()
méthodes et de construire paresseusement la chaîne SQL "réelle" chaque fois que l'un des lesexecuteXXX()
méthodes sont appelées (tout un travail, mais la plupart des IDE fournissent des générateurs automatiques pour les méthodes décoratrices, Eclipse le fait). Enfin, utilisez-le à la place. C'est aussi fondamentalement ce que P6Spy et ses consorts font déjà sous le capot.la source
logger.debug(sql + " " + Arrays.asList(values))
- je cherche un moyen de consigner l'instruction SQL avec les paramètres déjà intégrés. Sans me boucler et remplacer les points d'interrogation.PreparedStatement
chaque fois. N'est-ce pas une manière pas si efficacePreparedStatement
de les créer une fois et de les réutiliser partout?J'utilise Java 8, pilote JDBC avec connecteur MySQL v. 5.1.31.
Je peux obtenir une vraie chaîne SQL en utilisant cette méthode:
Donc, il retourne comme ceci:
la source
Apache Derby
?Si vous exécutez la requête et attendez un
ResultSet
(vous êtes au moins dans ce scénario), vous pouvez simplement appelerResultSet
lesgetStatement()
comme ceci:La variable
executedQuery
contiendra l'instruction qui a été utilisée pour créer leResultSet
.Maintenant, je réalise que cette question est assez ancienne, mais j'espère que cela aidera quelqu'un.
la source
J'ai extrait mon sql de PreparedStatement en utilisant prepareStatement.toString () Dans mon cas, toString () retourne String comme ceci:
Maintenant, j'ai créé une méthode (Java 8), qui utilise regex pour extraire à la fois la requête et les valeurs et les mettre dans la carte:
Cette méthode renvoie la carte où nous avons des paires clé-valeur:
Maintenant, si vous voulez des valeurs sous forme de liste, vous pouvez simplement utiliser:
Si votre prepareStatement.toString () est différent de mon cas, c'est juste une question de "réglage" de regex.
la source
Utilisation de PostgreSQL 9.6.x avec le pilote Java officiel
42.2.4
:Montrera le SQL avec le
?
déjà remplacé, ce que je cherchais. Je viens d'ajouter cette réponse pour couvrir l'affaire postgres.Je n'aurais jamais pensé que cela pouvait être aussi simple.
la source
J'ai implémenté le code suivant pour imprimer SQL à partir de PrepareStatement
la source
Extrait de code pour convertir SQL PreparedStaments avec la liste des arguments. Ça marche pour moi
la source
Très tard :) mais vous pouvez obtenir le SQL d'origine à partir d'un OraclePreparedStatementWrapper par
la source
oracle.jdbc.driver.OraclePreparedStatementWrapper
n'est pas public dans oracle.jdbc.driver. Ne peut pas être accédé depuis un package extérieur. Comment utilisez-vous cette classe?Si vous utilisez MySQL, vous pouvez enregistrer les requêtes en utilisant le journal des requêtes de MySQL . Je ne sais pas si d'autres fournisseurs proposent cette fonctionnalité, mais il y a de fortes chances qu'ils le fassent.
la source
Fonctionne simplement:
C'est bien aussi pour PreparStatement.
la source
.toString()
avec quelques lignes supplémentaires pour tromper les utilisateurs inexpérimentés, et a déjà été répondu il y a longtemps.J'utilise Oralce 11g et je n'ai pas réussi à obtenir le SQL final à partir du PreparedStatement. Après avoir lu la réponse de @Pascal MARTIN, je comprends pourquoi.
J'ai juste abandonné l'idée d'utiliser PreparedStatement et utilisé un formateur de texte simple qui répondait à mes besoins. Voici mon exemple:
Vous comprenez que sqlInParam peut être construit de manière dynamique dans une boucle (for, while).
la source
((OraclePreparedStatementWrapper) myPreparedStatement).getOriginalSql()
Pour ce faire, vous avez besoin d'une connexion JDBC et / ou d'un pilote qui prend en charge la journalisation du SQL à un niveau bas.
Jetez un œil à log4jdbc
la source