Comment enregistrer des instructions SQL dans Grails

86

Je veux me connecter dans la console ou dans un fichier, toutes les requêtes que Grails fait, pour vérifier les performances.

J'avais configuré cela sans succès.

N'importe quelle idée aiderait.

user2427
la source
Aucune des solutions proposées ne fonctionne pour moi. J'écris ceci juste pour que tout le monde sache à quel point je suis désespéré.
Andrea

Réponses:

131

Réglage

datasource {
...
logSql = true
}

dans DataSource.groovy (selon ces instructions) était suffisant pour le faire fonctionner dans mon environnement. Il semble que certaines parties de la FAQ soient obsolètes (par exemple, la question «les colonnes plusieurs à plusieurs en arrière»), donc cela pourrait aussi être quelque chose qui a changé entre-temps.

Tomislav Nakic-Alfirevic
la source
6
logSql=trueseul ne suffit pas. La journalisation Hibernate doit également être activée. Voir la réponse de @ Pete.
Jason
2
J'ai remarqué que cela n'inclut pas les valeurs qui vont dans les instructions SQL où se trouvent les "?".
Jason
1
Cela fonctionne, mais pour toutes les requêtes. Est-il également possible d'imprimer le sql généré pour un critère particulier sans avoir à définir logSql = true?
août
@Guus comment puis-je imprimer le SQL généré pour un critère particulier?
biniam
@biniam_Ethiopia Autant que je sache, ce n'est pas possible. Je veux cela aussi bien que c'est ennuyeux pour le débogage de certaines classes et ne pas vouloir voir d'autres requêtes également.
Août
91

Je trouve plus utile de faire ce qui suit, qui consiste à activer la journalisation d'Hibernate pour enregistrer le SQL avec les variables de liaison (afin que vous puissiez voir les valeurs passées dans vos appels et répliquer facilement le SQL dans votre éditeur ou autre).

Dans votre Config.groovy, ajoutez ce qui suit à votre bloc log4j:

log4j = {

    // Enable Hibernate SQL logging with param values
    trace 'org.hibernate.type'
    debug 'org.hibernate.SQL'
    //the rest of your logging config
    // ...
    }
Peter
la source
8
Je l'ai utilisé plusieurs fois. Une chose à noter: la sortie des paramètres est très coûteuse. Je recommanderais de le faire uniquement sur votre boîte de développement.
John Gordon
2
Vous pouvez également ajouter format_sql = truedans le hibernatebloc de votre DataSource.groovypour une sortie joliment formatée.
Gregor Petrin
1
Remarque: Cela enregistrera à la fois les paramètres de clause where et les valeurs de colonne extraites des ensembles de résultats de requête. Pour consigner uniquement les paramètres de clause where, utiliseztrace 'org.hibernate.type.BasicBinder'
GreenGiant
Quelqu'un connaît-il l'équivalent pour les grails 3.3.8?
John Little
Pour une raison quelconque, les requêtes syntaxiquement non valides (générées par Hibernate lui-même, malheureusement!) Ne sont pas enregistrées - toutes les autres requêtes sont enregistrées ... Peut-être un problème avec Hibernate lui-même?
Janaka Bandara
32

Pour les Grains 3. *

Option # 1, ajoutez ce qui suit à logback.groovy

logger("org.hibernate.SQL", DEBUG, ["STDOUT"], false)
logger("org.hibernate.type.descriptor.sql.BasicBinder", TRACE, ["STDOUT"], false)

ou

L'option n ° 2 ajoute ce qui suit à dataSource dans le fichier application.yml. Cependant, cette approche n'enregistre pas les valeurs des paramètres

environments:
  local:
    dataSource:
        logSql: true
        formatSql: true
Robert Hutto
la source
17

Essaye ça:

log4j = {
   ...
   debug 'org.hibernate.SQL'
   trace 'org.hibernate.type.descriptor.sql.BasicBinder'
}

Cela évite les problèmes de performances liés à la journalisation de trace du typepaquet Hibernate . Cela fonctionne avec Hibernate 3.6 et versions ultérieures. J'ai obtenu ceci de: https://burtbeckwith.com/blog/?p=1604

Jason
la source
6

La solution ne concerne que le développement, pas la production.

Toutes les réponses ci-dessus fonctionnent et sont correctes. Mais ils ne montrent pas la requête complète d'une manière lisible par l'homme. Si vous voulez voir la requête finale (sans aucune?,?), Vous avez deux options.

A) proxy de votre connexion jdbc avec log4jdbc ou p6Spy.

B) regardez-le au niveau de la base de données. Par exemple, très facile à faire avec mysql.

Découvrez où se trouve votre fichier general_log_file. Journal général actif si non déjà activé.

mysql command line> show variables like "%general_log%";
mysql command line> set global general_log = true;

Maintenant, tout est enregistré dans votre fichier journal. Exemple Mac / Linux pour afficher un joli flux de vos requêtes.

tail -f path_to_log_file 
Wuestenfuchs
la source
3

Pure pour référence seulement, mais j'utilise p6spy pour enregistrer les requêtes SQL. C'est un petit pilote jdbc intermédiaire. La requête exacte est enregistrée comme elle serait envoyée au serveur (avec les paramètres inclus).

incluez-le dans votre projet:

runtime 'p6spy:p6spy:3.0.0'

Changez votre pilote de source de données:

driverClassName: com.p6spy.engine.spy.P6SpyDriver

Et votre URL jdbc:

url: jdbc:p6spy:mysql://

Configurez-le en utilisant spy.properties (dans grails-app / conf).

driverlist=org.h2.Driver,com.mysql.jdbc.Driver
autoflush=true
appender=com.p6spy.engine.spy.appender.StdoutLogger
databaseDialectDateFormat=yyyy-MM-dd
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat

N'oubliez pas de désactiver cela pour la production!

Dennie de Lange
la source
2

Next fonctionne pour moi:

grails-app / conf / application.yml

# ...
hibernate:
    format_sql: true # <<<<<<< ADD THIS <<<<<<<
    cache:
        queries: false
        use_second_level_cache: true
# ...
environments:
    development:
        dataSource:
            logSql: true // <<<<<<< ADD THIS <<<<<<<
            dbCreate: create-drop
            url: jdbc:h2:mem:...
# ...

grails-app / conf / logback.groovy

// ...
appender('STDOUT', ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
        pattern = "%level %logger - %msg%n"
    }
}

// >>>>>>> ADD IT >>>>>>>
logger 'org.hibernate.type.descriptor.sql.BasicBinder', TRACE, ['STDOUT']
logger 'org.hibernate.SQL', TRACE, ['STDOUT']
// <<<<<<< ADD IT <<<<<<<

root(ERROR, ['STDOUT'])

def targetDir = BuildSettings.TARGET_DIR
// ...

Source: http://sergiodelamo.es/log-sql-grails-3-app/

Eduardo Cuomo
la source
1

Je sais que cela a été demandé et répondu il y a longtemps. J'espère que cela vous aidera.

Actuellement, il est dans un environnement de développement. Nous utilisons "log4jdbc Driver Spy" pour enregistrer sql.

Configuration:

Dans votre BuildConfig.groovy: ajoutez ci-dessous les dépendances:

dependencies {
.....
runtime 'org.lazyluke:log4jdbc-remix:0.2.7'
}

Et dans votre DataSource ou autre configuration liée: [partout où vous avez défini la configuration liée à la source de données], ajoutez:

datasources{
.....
driverClassName: "net.sf.log4jdbc.DriverSpy",
url: "jdbc:log4jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = XXXXX.XX>XXX)(PORT = 1521))) (CONNECT_DATA = (SID = XXXX)(SERVER =DEDICATED)))",
....
}
log4j = {

    info 'jdbc.sqlonly' //, 'jdbc.resultsettable'

}

D'après mon expérience personnelle, je l'ai trouvé très utile et utile lors du débogage. Vous trouverez également plus d'informations sur ce site. https://code.google.com/p/log4jdbc-remix/

Salutations du roi

Madhu Bose
la source
0

Pour un bloc de code particulier, nous pouvons également créer une méthode qui accepte une fermeture. par exemple.

 static def executeBlockAndGenerateSqlLogs(Closure closure) {
    Logger sqlLogger = Logger.getLogger("org.hibernate.SQL");
    Level currentLevel = sqlLogger.level
    sqlLogger.setLevel(Level.TRACE)
    def result = closure.call()
    sqlLogger.setLevel(currentLevel)
    result }

executeBlockAndGenerateSqlLogs{DomainClazz.findByPropertyName("property value")}
akashsethi
la source
0

Si vous avez installé le plugin de console , vous pouvez obtenir une journalisation SQL avec ce petit extrait de code.

// grails 2.3
def logger=ctx.sessionFactory.settings.sqlStatementLogger

// grails 3.3  
def logger = ctx.sessionFactory.currentSession.jdbcCoordinator.statementPreparer.jdbcService.sqlStatementLogger

logger.logToStdout=true    
try {
   <code that will log sql queries>
}
finally {
    logger.logToStdout = false
}

Il s'agit d'une variante de la plupart des solutions ci-dessus, mais vous permet de modifier la valeur au moment de l'exécution. Et tout comme les autres solutions qui le traitent, logToStdoutaffiche uniquement les requêtes et non les valeurs de liaison.

L'idée a été volée à un burtbeck avec un post que j'ai lu il y a quelques années que je ne trouve pas pour le moment. Il a été édité pour fonctionner avec Grails 3.3.

Une technique similaire peut être utilisée pour activer la journalisation pour des tests d'intégration spécifiques:

class SomeIntegrationSpec extends IntegrationSpec {

    def sessionFactory

    def setup() {
        sessionFactory.settings.sqlStatementLogger.logToStdout = true
    }

    def cleanup() {
        sessionFactory.settings.sqlStatementLogger.logToStdout = false
    }

    void "some test"() {
           ...
    }

Cela activera la journalisation SQL uniquement pour les tests de ce fichier.

des brûlures
la source