Як реєструвати оператори SQL у Grails


86

Я хочу увійти в консоль або у файл, усі запити, які робить Grails, щоб перевірити продуктивність.

Я налаштував це без успіху.

Будь-яка ідея допомогла б.


Жодне із запропонованих рішень не працює для мене. Я пишу це лише для того, щоб усі знали, як я зневірена.
Андреа

Відповіді:


131

Налаштування

datasource {
...
logSql = true
}

в DataSource.groovy (відповідно до цих інструкцій) було достатньо, щоб він працював у моєму середовищі. Здається, що частини часто заданих питань застаріли (наприклад, запитання "стовпці" багато-до-багатьох назад "), тому це також може щось змінити тим часом.


6
logSql=trueодного недостатньо. Журнал сплячого режиму теж потрібно ввімкнути. Дивіться відповідь @ Pete.
Джейсон

2
Я помітив, що сюди не входять значення, які містяться в операторах SQL там, де знаки "?".
Джейсон

1
Це працює, але для всіх запитів. Чи можна також надрукувати згенерований sql для певних Критеріїв, не встановлюючи logSql = true?
серпня

@Guus, як я можу надрукувати згенерований sql для певних Критеріїв?
biniam

@biniam_Ethiopia Наскільки мені відомо, це неможливо. Я хочу цього, а також це дратує для налагодження певних класів, а також не бачення інших запитів.
серпня

91

Я вважаю, що більш корисним було зробити наступне, тобто включити журналювання Hibernate для реєстрації SQL разом із змінними прив'язки (щоб ви могли бачити значення, передані у ваші виклики, і легко копіювати SQL у вашому редакторі чи іншим чином).

У ваших Config.groovy, додайте наступний рядок в ваш log4j блоку:

log4j = {

    // Enable Hibernate SQL logging with param values
    trace 'org.hibernate.type'
    debug 'org.hibernate.SQL'
    //the rest of your logging config
    // ...
    }

8
Я використовував це багато разів. Зауважимо одне: виведення параметрів дуже дороге. Я б рекомендував робити це лише на вашому розробнику.
Джон Гордон,

2
Ви також можете додати format_sql = trueдо hibernateблоку вашого DataSource.groovyфайлу для красиво відформатованого виводу.
Грегор Петрін

1
Примітка: Це реєструватиме як параметри речення, так і значення стовпців, витягнуті з наборів результатів запиту. Щоб реєструвати лише параметри пропозиції, використовуйтеtrace 'org.hibernate.type.BasicBinder'
GreenGiant

Хтось знає еквівалент для граалів 3.3.8?
Джон Літтл

З якоїсь причини синтаксично недійсні запити (генеровані самим Hibernate, на жаль!) ​​Не реєструються - усі інші запити реєструються ... Можливо, проблема з самим Hibernate?
Janaka Bandara

31

Для граалів 3. *

Варіант №1 додайте наступне до logback.groovy

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

або

Варіант №2 додає наступне до dataSource у застосунку.yml. Однак цей підхід не реєструє значення параметрів

environments:
  local:
    dataSource:
        logSql: true
        formatSql: true

17

Спробуйте це:

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

Це дозволяє уникнути проблем із продуктивністю журналювання трасування typeпакета Hibernate . Це працює з Hibernate 3.6 і вище. Я отримав це з: https://burtbeckwith.com/blog/?p=1604


6

Рішення призначене лише для розробки, а не для виробництва.

Усі відповіді вище працюють і є правильними. Але вони не відображають повний запит у приємній для читання формі. Якщо ви хочете побачити остаточний (без будь-якого?,?) Запиту, у вас є два варіанти.

А) встановіть проксі-з'єднання jdbc з log4jdbc або p6Spy.

Б) розгляньте це на рівні бази даних. Наприклад, дуже легко зробити за допомогою mysql.

Дізнайтеся, де знаходиться файл general_log_. Активний загальний журнал, якщо його ще не активовано.

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

Тепер все реєструється у вашому файлі журналу. Приклад Mac / linux, щоб показати приємний потік ваших запитів.

tail -f path_to_log_file 

3

Чисто лише для довідки, але я використовую p6spy для реєстрації запитів SQL. Це невеликий проміжний драйвер jdbc. Точний запит реєструється, оскільки він буде відправлений на сервер (із включеними параметрами).

включіть його у свій проект:

runtime 'p6spy:p6spy:3.0.0'

Змініть драйвер джерела даних:

driverClassName: com.p6spy.engine.spy.P6SpyDriver

І ваша адреса jdbc:

url: jdbc:p6spy:mysql://

Налаштуйте його за допомогою spy.properties (у 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

Не забудьте вимкнути це для виробництва!


2

Наступна робота для мене:

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
// ...

Джерело: http://sergiodelamo.es/log-sql-grails-3-app/


1

Я знаю, що на це вже давно запитували і відповідали. Але я щойно побачив це запитання і не міг зупинити себе, щоб відповісти чи поділитися нашим підходом до введення журналу sql у нашому проекті. Сподіваюся, це допоможе.

В даний час він знаходиться в середовищі розробки. Ми використовуємо "log4jdbc Driver Spy" для реєстрації sql.

Конфігурація:

У вашому BuildConfig.groovy: додайте нижче залежності:

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

А у вашому DataSource або іншій конфігурації: [де б ви не визначили конфігурацію, пов’язану з джерелом даних], додайте:

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'

}

З мого особистого досвіду я знайшов це дуже корисним та корисним під час налагодження. Також більше інформації ви можете знайти на цьому веб-сайті.https://code.google.com/p/log4jdbc-remix/

З повагою


0

Для певного блоку коду ми також можемо створити метод, який приймає закриття. напр.

 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")}

0

Якщо у вас встановлений консольний плагін, ви можете отримати журнал sql за допомогою цього невеликого фрагмента коду.

// 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
}

Це варіація багатьох наведених вище рішень, але дозволяє змінити значення під час виконання. І так само, як інші рішення, які мають справу з logToStdoutцим, показують лише запити, а не значення прив’язки.

Ідею вкрали з місця, яке я прочитав кілька років тому, і якого я зараз не можу знайти. Він відредагований для роботи з граалями 3.3.

Подібний прийом можна використовувати для ввімкнення журналювання для конкретних тестів інтеграції:

class SomeIntegrationSpec extends IntegrationSpec {

    def sessionFactory

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

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

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

Це увімкне ведення журналу sql лише для тестів у цьому одному файлі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.