วิธีบันทึกคำสั่ง SQL ใน Grails


86

ฉันต้องการเข้าสู่คอนโซลหรือในไฟล์แบบสอบถามทั้งหมดที่ Grails ทำเพื่อตรวจสอบประสิทธิภาพ

ฉันกำหนดค่านี้ไม่สำเร็จ

ความคิดใด ๆ จะช่วยได้


ไม่มีวิธีแก้ปัญหาใดที่ใช้ได้ผลสำหรับฉัน ฉันเขียนสิ่งนี้เพื่อให้ทุกคนรู้ว่าฉันหมดหวังแค่ไหน
Andrea

คำตอบ:


131

การตั้งค่า

datasource {
...
logSql = true
}

ใน DataSource.groovy (ตามคำแนะนำเหล่านี้ ) ก็เพียงพอที่จะทำให้ใช้งานได้ในสภาพแวดล้อมของฉัน ดูเหมือนว่าบางส่วนของคำถามที่พบบ่อยจะล้าสมัยไปแล้ว (เช่นคำถาม "คอลัมน์แบบหลายต่อหลายคอลัมน์ย้อนหลัง") ดังนั้นจึงอาจมีบางอย่างที่เปลี่ยนแปลงไปในระหว่างนี้


6
logSql=trueอย่างเดียวไม่เพียงพอ ต้องเปิดการบันทึกไฮเบอร์เนตด้วย ดูคำตอบของ @ Pete
Jason

2
ฉันสังเกตว่าสิ่งนี้ไม่รวมค่าที่อยู่ในคำสั่ง SQL โดยที่ "?" อยู่
Jason

1
วิธีนี้ใช้ได้ แต่สำหรับการค้นหาทั้งหมด เป็นไปได้ไหมที่จะพิมพ์ sql ที่สร้างขึ้นสำหรับ Criteria โดยไม่ต้องตั้งค่า logSql = true
สิงหาคม

@Guus ฉันจะพิมพ์ sql ที่สร้างขึ้นสำหรับ Criteria เฉพาะได้อย่างไร
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
ผมใช้หลายครั้งแล้ว สิ่งหนึ่งที่ควรทราบ: การส่งออกพารามิเตอร์มีราคาแพงมาก ฉันอยากจะแนะนำให้ทำสิ่งนี้ในกล่อง dev ของคุณเท่านั้น
John Gordon

2
คุณยังสามารถเพิ่มformat_sql = trueเข้าไปในhibernateบล็อกของคุณDataSource.groovyเพื่อให้ได้ผลลัพธ์ที่มีรูปแบบสวยงาม
Gregor Petrin

1
หมายเหตุ: สิ่งนี้จะบันทึกทั้งโดยที่พารามิเตอร์ประโยคและค่าคอลัมน์ที่ดึงมาจากชุดผลลัพธ์การสืบค้น หากต้องการบันทึกเฉพาะที่พารามิเตอร์ของประโยคให้ใช้trace 'org.hibernate.type.BasicBinder'
GreenGiant

ใครรู้ว่าเทียบเท่ากับ grails 3.3.8?
John Little

ด้วยเหตุผลบางประการข้อความค้นหาที่ไม่ถูกต้องทางไวยากรณ์ (สร้างโดย Hibernate เองน่าเศร้า!) ไม่ได้รับการบันทึก - ข้อความค้นหาอื่น ๆ ทั้งหมดจะถูกบันทึก ... อาจเป็นปัญหากับ Hibernate เองหรือไม่?
Janaka Bandara

32

สำหรับจอก 3. *

ตัวเลือก # 1 เพิ่มสิ่งต่อไปนี้ใน logback.groovy

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

หรือ

ตัวเลือก # 2 เพิ่มสิ่งต่อไปนี้ใน dataSource ใน application.yml อย่างไรก็ตามวิธีนี้ไม่ได้บันทึกค่าพารามิเตอร์

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

17

ลองสิ่งนี้:

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

หลีกเลี่ยงปัญหาด้านประสิทธิภาพของการติดตามการบันทึกtypeแพ็กเกจไฮเบอร์เนต ใช้งานได้กับ Hibernate 3.6 ขึ้นไป ฉันได้รับสิ่งนี้จาก: https://burtbeckwith.com/blog/?p=1604


6

โซลูชันมีไว้สำหรับการพัฒนาเท่านั้นไม่ใช่การผลิต

คำตอบทั้งหมดข้างต้นใช้ได้ผลและถูกต้อง แต่จะไม่แสดงข้อความค้นหาที่สมบูรณ์ในรูปแบบที่มนุษย์สามารถอ่านได้ หากต้องการดูแบบสอบถามสุดท้าย (โดยไม่มี?,?) คุณมีสองตัวเลือก

ก) พร็อกซีการเชื่อมต่อ jdbc ของคุณด้วย log4jdbc หรือ p6Spy

B) ดูที่ระดับฐานข้อมูล ยกตัวอย่างง่ายๆด้วย mysql

ค้นหาว่าคุณ general_log_file อยู่ที่ไหน บันทึกทั่วไปที่ใช้งานอยู่หากยังไม่มีการเปิดใช้งาน

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 ของคุณ:

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

และในแหล่งข้อมูลของคุณหรือการกำหนดค่าอื่น ๆ ที่เกี่ยวข้อง: [ที่ใดก็ตามที่คุณกำหนดคอนฟิกูเรชันที่เกี่ยวข้องกับแหล่งข้อมูล] ให้เพิ่ม:

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มันจะแสดงเฉพาะแบบสอบถามไม่ใช่ค่าการผูก

ความคิดนี้ถูกขโมยไปจากโพสต์ของ Burtbeckwith ที่ฉันอ่านเมื่อหลายปีก่อนซึ่งตอนนี้ฉันหาไม่เจอ ได้รับการแก้ไขให้ทำงานกับ grails 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 สำหรับการทดสอบในไฟล์เดียวนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.