176 votes

Comment puis-je obtenir le code SQL d’une classe PreparedStatement ?

J'ai une méthode en Java avec la signature de méthode suivante:

private static ResultSet runSQLResultSet(String sql, Object... queryParams)

L'ouverture d'une connexion, construit un PreparedStatement à l'aide de l'instruction sql et les paramètres de l' queryParams de longueur variable tableau, l'exécute, met l' ResultSet (en CachedRowSetImpl), ferme la connexion, et retourne le jeu de résultats du cache.

J'ai la manipulation d'exception dans la méthode qui enregistre les erreurs. J'journal de l'instruction sql en tant que partie du journal, car il est très utile pour le débogage. Mon problème est que l'enregistrement de la variable de Chaîne sql journaux le modèle de déclaration ?'s au lieu des valeurs réelles. Je veux ouvrir une session le réel instruction a été exécutée (ou essayé de l'exécuter).

Alors... Est-il possible d'obtenir le véritable instruction SQL qui sera exécutée par un PreparedStatement? (Sans le construire moi-même. Si je ne peux pas trouver un moyen d'accéder à l' PreparedStatement's SQL, je vais probablement jusqu'à la fin de la construire moi-même dans mes catches.)

183voto

Pascal MARTIN Points 195780

À l'aide de déclarations préparées à l'avance, il n'y a pas de "requête SQL" :

  • Vous avez un énoncé, contenant des espaces réservés
    • il est envoyé vers le serveur de base de données
    • et préparé
    • ce qui signifie que l'instruction SQL est "analysée", analysé, certaines structures de données représentant, il est préparé dans la mémoire
  • Et, alors, vous avez variables liées à la
    • qui sont envoyées au serveur
    • et l'instruction préparée est exécutée -- à travailler sur ces données

Mais il n'y a pas de re-construction d'un vrai requête SQL -- ni sur le JAVA côté, ni sur le côté de la base de données.

Donc, il n'y a aucun moyen d'obtenir le prêt de l'instruction SQL -- comme il n'existe pas de telles SQL.


Fin de débogage, les solutions sont soit de :

  • En sortie le code de l'instruction, avec les espaces réservés ; et la liste de données
  • Ou à "construire" une requête SQL "à la main".

61voto

BalusC Points 498232

Il est nulle part défini dans l'API JDBC contrat, mais si vous avez de la chance, le pilote JDBC en question peut renvoyer le SQL complète simplement en appelant PreparedStatement#toString(). I. e.

System.out.println(preparedStatement);

La plupart des pilotes JDBC ne le supporte pas. Si vous en avez un, alors votre meilleur pari est d'utiliser P6Spy.

Alternativement, vous pouvez aussi écrire une fonction générique qui prend en Connection, une chaîne SQL et la déclaration de valeurs et qui renvoie un PreparedStatement après l'enregistrement de la chaîne SQL et les valeurs. Le coup d'envoi exemple:

public static PreparedStatement prepareStatement(Connection connection, String sql, Object... values) throws SQLException {
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    for (int i = 0; i < values.length; i++) {
        preparedStatement.setObject(i + 1, values[i]);
    }
    logger.debug(sql + " " + Arrays.asList(values));
    return preparedStatement;
}

et l'utiliser comme

try {
    connection = database.getConnection();
    preparedStatement = prepareStatement(connection, SQL, values);
    resultSet = preparedStatement.executeQuery();
    // ...

Une autre alternative est de mettre en œuvre une coutume PreparedStatement qui s'enroule (orne) le réel PreparedStatement sur la construction et remplace toutes les méthodes de sorte qu'il appelle les méthodes du réel PreparedStatement et recueille les valeurs dans tous les setXXX() méthodes et paresseusement construit le "réel" chaîne SQL à chaque fois que l'un de la executeXXX() méthodes est appelée (tout un travail, mais la plupart des IDE fournit autogenerators pour décorateur méthodes, Eclipse n'). Enfin, il suffit de l'utiliser à la place. C'est aussi, fondamentalement, ce que P6Spy et consorts font déjà sous le capot.

0voto

Ionuț G. Stan Points 62482

Si vous utilisez MySQL, vous pouvez enregistrer les requêtes à l’aide du Journal des requêtes MySQL. Je ne sais pas si les autres fournisseurs fournissent cette fonctionnalité, mais les chances sont qu’ils font.

-1voto

samimvp Points 66

ici un exemple de la façon dont vous pouvez obtenir le code sql de la http://www.avajava.com/tutorials/lessons/how-do-i-display-a-prepared-statement-with-bind-variables-using-mysql.html perperated déclaration

Il suffit de faire prepStmt.toString()

-4voto

sidereal Points 749

Pour ce faire, vous avez besoin d’une connexion JDBC et/ou un pilote qui prend en charge la journalisation sql à un niveau bas.

Jetez un oeil à log4jdbc

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X