วิธีพิมพ์สตริงแบบสอบถามที่มีค่าพารามิเตอร์เมื่อใช้ Hibernate


393

เป็นไปได้ไหมที่ Hibernate ที่จะพิมพ์แบบสอบถาม SQL ที่สร้างขึ้นด้วยค่าจริงแทนที่จะทำเครื่องหมายคำถาม?

คุณจะแนะนำให้พิมพ์คิวรีที่มีค่าจริงอย่างไรหากไม่สามารถทำได้ด้วย Hibernate API


คำตอบ:


425

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

  • org.hibernate.SQL   - ตั้งค่าให้debugบันทึกคำสั่ง SQL DML ทั้งหมดขณะที่ถูกดำเนินการ
  • org.hibernate.type- ตั้งค่าเป็นtraceบันทึกพารามิเตอร์ JDBC ทั้งหมด

ดังนั้นการกำหนดค่า log4j อาจมีลักษณะดังนี้:

# logs the SQL statements
log4j.logger.org.hibernate.SQL=debug 

# Logs the JDBC parameters passed to a query
log4j.logger.org.hibernate.type=trace 

ครั้งแรกเทียบเท่ากับคุณสมบัติhibernate.show_sql=trueดั้งเดิมที่สองพิมพ์พารามิเตอร์ที่ถูกผูกไว้ในหมู่สิ่งอื่น ๆ

วิธีอื่น (ที่ไม่ใช่จำศีล based) จะใช้พร็อกซี่ไดรเวอร์ JDBC เช่นP6Spy


11
สิ่งนี้มีประโยชน์ แต่นี่ไม่ได้แสดงคิวรี่ SQL จริงให้ฉันดู
Nicolas Barbulesco

6
@ Nicolas นั้นเป็นความจริงอย่างไรก็ตามหลังจากการสอบถามมันก็จะแจกแจงพารามิเตอร์ที่ถูกผูกไว้
Xtreme Biker

2
ฉันใช้ grails 2.4.4 และ hibernate 4. การเปลี่ยนการกำหนดค่า log4j ไม่ทำงานสำหรับฉัน แต่ p6spy ทำงาน!
แชมป์

10
ใน Hibernate 5 เราสามารถใช้ตัวorg.hibernate.type.descriptor.sql.BasicBinderบันทึก การเปิดใช้งานการเข้าสู่ระบบสำหรับorg.hibernate.typeพิมพ์ข้อมูลที่ไร้ประโยชน์มากเกินไปสำหรับฉัน ...
csharpfolk

5
org.hibernate.typeและorg.hibernate.loader.hqlไม่ทำงานสำหรับฉันที่จะแสดงพารามิเตอร์
Dherik

75

เพียงเพื่อความสะดวกนี่คือตัวอย่างการกำหนดค่าเดียวกันสำหรับ Logback (SLF4J)

<appender name="SQLROLLINGFILE">
 <File>/tmp/sql.log</File>
 <rollingPolicy>
  <FileNamePattern>logFile.%d{yyyy-MM-dd}.log</FileNamePattern>
 </rollingPolicy>
 <layout>
  <Pattern>%-4date | %msg %n</Pattern>
 </layout>
</appender>

<logger name="org.hibernate.SQL" additivity="false" >   
 <level value="DEBUG" />    
 <appender-ref ref="SQLROLLINGFILE" />
</logger>

<logger name="org.hibernate.type" additivity="false" >
 <level value="TRACE" />
 <appender-ref ref="SQLROLLINGFILE" />
</logger>

ผลลัพธ์ใน sql.log ของคุณ (ตัวอย่าง) จะมีลักษณะดังนี้:

2013-08-30 18:01:15,083 | update stepprovider set created_at=?, lastupdated_at=?, version=?, bundlelocation=?, category_id=?, customer_id=?, description=?, icon_file_id=?, name=?, shareStatus=?, spversion=?, status=?, title=?, type=?, num_used=? where id=?
2013-08-30 18:01:15,084 | binding parameter [1] as [TIMESTAMP] - 2012-07-11 09:57:32.0
2013-08-30 18:01:15,085 | binding parameter [2] as [TIMESTAMP] - Fri Aug 30 18:01:15 CEST 2013
2013-08-30 18:01:15,086 | binding parameter [3] as [INTEGER] -
2013-08-30 18:01:15,086 | binding parameter [4] as [VARCHAR] - com.mypackage.foo
2013-08-30 18:01:15,087 | binding parameter [5] as [VARCHAR] -
2013-08-30 18:01:15,087 | binding parameter [6] as [VARCHAR] -
2013-08-30 18:01:15,087 | binding parameter [7] as [VARCHAR] - TODO
2013-08-30 18:01:15,087 | binding parameter [8] as [VARCHAR] -
2013-08-30 18:01:15,088 | binding parameter [9] as [VARCHAR] - MatchingStep@com.mypackage.foo
2013-08-30 18:01:15,088 | binding parameter [10] as [VARCHAR] - PRIVATE
2013-08-30 18:01:15,088 | binding parameter [11] as [VARCHAR] - 1.0
2013-08-30 18:01:15,088 | binding parameter [12] as [VARCHAR] - 32
2013-08-30 18:01:15,088 | binding parameter [13] as [VARCHAR] - MatchingStep
2013-08-30 18:01:15,089 | binding parameter [14] as [VARCHAR] -
2013-08-30 18:01:15,089 | binding parameter [15] as [INTEGER] - 0
2013-08-30 18:01:15,089 | binding parameter [16] as [VARCHAR] - 053c2e65-5d51-4c09-85f3-2281a1024f64

2
นี่ไม่ได้ตอบคำถาม OPs
ShadowGames

33

เปลี่ยนhibernate.cfg.xmlเป็น:

<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>

รวม log4j และรายการด้านล่างใน "log4j.properties":

log4j.logger.org.hibernate=INFO, hb
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE

log4j.appender.hb=org.apache.log4j.ConsoleAppender
log4j.appender.hb.layout=org.apache.log4j.PatternLayout

ขอบคุณทำงานได้ดีสำหรับฉันจริงๆ ตั้งค่าเหล่านั้นจะเพิ่มภายใต้แบบสอบถาม SQL binding parameter [1] as [VARCHAR] - [1]พารามิเตอร์เช่น
G. Ciardini

28

ในกรณีที่ใช้สปริงบูทให้กำหนดค่านี้:

aplication.yml

logging:
  level:
    org.hibernate.SQL: DEBUG
    org.hibernate.type: TRACE

aplication.properties

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE

และไม่มีอะไรเพิ่มเติม

HTH


20

Log4JDBC เป็นทางออกที่ดีที่จะพิมพ์SQL ที่แน่นอนไปยังฐานข้อมูลพร้อมพารามิเตอร์ในสถานที่แทนที่จะเป็นคำตอบที่ได้รับความนิยมมากที่สุดที่นี่ซึ่งไม่ได้ทำเช่นนี้ สิ่งอำนวยความสะดวกที่สำคัญอย่างหนึ่งคือคุณสามารถคัดลอก SQL ไปยังส่วนหน้าของฐานข้อมูลของคุณโดยตรงและดำเนินการตามที่เป็นอยู่

http://log4jdbc.sourceforge.net/

https://code.google.com/p/log4jdbc-remix/

หลังยังแสดงผลลัพธ์แบบตารางของผลลัพธ์แบบสอบถาม

เอาต์พุตตัวอย่างแสดง SQL ที่สร้างขึ้นพร้อม params พร้อมกับตารางชุดผลลัพธ์จากเคียวรี:

5. insert into ENQUIRY_APPLICANT_DETAILS (ID, INCLUDED_IN_QUOTE, APPLICANT_ID, TERRITORY_ID, ENQUIRY_ID, ELIGIBLE_FOR_COVER) values (7, 1, 11, 1, 2, 0) 


10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |---|--------|--------|-----------|----------|---------|-------|
10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |ID |CREATED |DELETED |CODESET_ID |NAME      |POSITION |PREFIX |
10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |---|--------|--------|-----------|----------|---------|-------|
10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |2  |null    |null    |1          |Country 2 |1        |60     |
10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |---|--------|--------|-----------|----------|---------|-------|

อัพเดท 2016

ล่าสุดฉันใช้ log4jdbc-log4j2 ( https://code.google.com/archive/p/log4jdbc-log4j2/ ) กับ SLF4j และ logback การพึ่งพา Maven ที่จำเป็นสำหรับการตั้งค่าของฉันมีดังนี้:

<dependency>
    <groupId>org.bgee.log4jdbc-log4j2</groupId>
    <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
    <version>1.16</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>${logback.version}</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>$logback.version}</version>
</dependency>

ไดร์เวอร์และ DB Urls มีลักษณะดังนี้:

database.driver.class=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
database.url=jdbc:log4jdbc:hsqldb:mem:db_name #Hsql
#database.url=jdbc:log4jdbc:mysql://localhost:3306/db_name 

ไฟล์กำหนดค่า logback.xml ของฉันมีลักษณะดังนี้: นี่เป็นผลลัพธ์ของคำสั่ง SQL ทั้งหมดพร้อมพารามิเตอร์รวมทั้งตาราง resultset สำหรับการสืบค้นทั้งหมด

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>

    <logger name="jdbc.audit" level="ERROR" />
    <logger name="jdbc.connection" level="ERROR" />
    <logger name="jdbc.sqltiming" level="ERROR" />
    <logger name="jdbc.resultset" level="ERROR" />

    <!-- UNCOMMENT THE BELOW TO HIDE THE RESULT SET TABLE OUTPUT -->
    <!--<logger name="jdbc.resultsettable" level="ERROR" /> -->

    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

ในที่สุดฉันต้องสร้างไฟล์ชื่อ log4jdbc.log4j2.properties ที่ root ของ classpath เช่น src / test / resources หรือ src / main / resources ในโครงการ Mevn ไฟล์นี้มีหนึ่งบรรทัดซึ่งอยู่ด้านล่าง:

log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator

ด้านบนจะขึ้นอยู่กับไลบรารีการบันทึกของคุณ ดูเอกสารได้ที่https://code.google.com/archive/p/log4jdbc-log4j2สำหรับข้อมูลเพิ่มเติม

ตัวอย่างผลลัพธ์:

10:44:29.400 [main] DEBUG jdbc.sqlonly -  org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
5. select memberrole0_.member_id as member_i2_12_0_, memberrole0_.id as id1_12_0_, memberrole0_.id 
as id1_12_1_, memberrole0_.member_id as member_i2_12_1_, memberrole0_.role_id as role_id3_12_1_, 
role1_.id as id1_17_2_, role1_.name as name2_17_2_ from member_roles memberrole0_ left outer 
join roles role1_ on memberrole0_.role_id=role1_.id where memberrole0_.member_id=104 

10:44:29.402 [main] INFO  jdbc.resultsettable - 
|----------|---|---|----------|--------|---|-----|
|member_id |id |id |member_id |role_id |id |name |
|----------|---|---|----------|--------|---|-----|
|----------|---|---|----------|--------|---|-----|

1
เฮ้ .... นี่มันเจ๋ง .... แค่หมอสั่งให้ฉัน :) ... แต่มันสนับสนุน CLOB / BLOB ด้วยหรือเปล่า? นอกจากนี้เป็นไปได้หรือไม่ที่จะแสดงเฉพาะคิวรี่ไม่ใช่ชุดผลลัพธ์ - ขอบคุณ :)
dev ray

1
คุณสามารถให้ตัวอย่างของการกำหนดค่าได้อย่างไร
grep

ที่จริงแล้วผลลัพธ์หลังเป็นตัวแทน tabluar ของผลลัพธ์การค้นหา ... นั่นคือต้องการ log4jdbc-remix สำหรับคุณลักษณะที่ดีนั้น
meriton

วิธีนี้ดีที่สุดสำหรับสถานการณ์ของฉันที่ฉันต้องการดูค่าหมายเลขแถวที่ Hibernate สร้างขึ้นสำหรับชุดผลลัพธ์การเพจ การบันทึกการติดตามแสดงเฉพาะค่าพารามิเตอร์เคียวรี
Oliver Hernandez

@Alan Hay บันทึกการสืบค้นดั้งเดิมนี้ด้วยหรือไม่
Sayantan

9

คุณสามารถเพิ่มบรรทัดหมวดหมู่เพื่อ log4j.xml:

<category name="org.hibernate.type">
    <priority value="TRACE"/>
</category>

และเพิ่มคุณสมบัติไฮเบอร์เนต:

<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>

7

เพิ่มคุณสมบัติและค่าต่อไปนี้ให้กับการกำหนดค่า log4j หรือ logback ของคุณ:

org.hibernate.sql=DEBUG
org.hibernate.type.descriptor.sql.BasicBinder=TRACE

5
org.hibernate.type.descriptor.sql.BasicBinderหมวดหมู่ไม่รวมพารามิเตอร์ทั้งหมดเช่น enum ประเภท ดังนั้นถ้าคุณต้องการทุกสิ่งคุณต้องการTRACEทั้งorg.hibernate.typeกลุ่มจริงๆ
seanf

สำหรับฉันมันใช้งานได้ในไฮเบอร์เนต 4.3! นอกจากนี้ฉันจะไม่ติดตาม org.hibernate.type แบบเต็มเพราะนั่นเป็นผลลัพธ์ที่มากเกินไป ในกรณีส่วนใหญ่การแก้ปัญหานี้จะทำ
cslotty

โปรดทราบว่า org.hibernate.type.descriptor.sql.BasicExtractor บันทึกชุดผลลัพธ์ ดังนั้นการมีรายการขนาดใหญ่อาจทำให้แอพพลิเคชั่นขัดข้องเมื่อทำการบันทึกในคอนโซลใน Eclipse และฉันคิดว่ามันไม่เหมาะสำหรับการเข้าสู่ไฟล์ นั่นคือเหตุผลที่ฉันชอบโซลูชันนี้มันยังทำงานใน Hibernate 3 สำหรับผู้ที่สนใจประเภท enum โปรดลองคลาสที่แน่นอนที่บันทึกไว้เมื่อ org.hibernate.type = TRACE จากนั้นตั้งค่า org.hibernate.type.xyz.TheClassThatLogsEnumParams = TRACE
Géza

7

คุณสามารถทำได้โดยใช้แหล่งข้อมูล-proxyตามที่ฉันอธิบายในโพสต์นี้

สมมติว่าแอปพลิเคชันของคุณคาดหวังdataSourceถั่ว (เช่นผ่าน@Resource) นี่คือวิธีที่คุณสามารถกำหนดค่าdatasource-proxy:

<bean id="actualDataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init"
  destroy-method="close">
    <property name="className" value="bitronix.tm.resource.jdbc.lrc.LrcXADataSource"/>
    <property name="uniqueName" value="actualDataSource"/>
    <property name="minPoolSize" value="0"/>
    <property name="maxPoolSize" value="5"/>
    <property name="allowLocalTransactions" value="false" />
    <property name="driverProperties">
        <props>
            <prop key="user">${jdbc.username}</prop>
            <prop key="password">${jdbc.password}</prop>
            <prop key="url">${jdbc.url}</prop>
            <prop key="driverClassName">${jdbc.driverClassName}</prop>
        </props>
    </property>
</bean>

<bean id="proxyDataSource" class="net.ttddyy.dsproxy.support.ProxyDataSource">
    <property name="dataSource" ref="testDataSource"/>
    <property name="listener">
        <bean class="net.ttddyy.dsproxy.listener.ChainListener">
            <property name="listeners">
                <list>
                    <bean class="net.ttddyy.dsproxy.listener.CommonsQueryLoggingListener">
                        <property name="logLevel" value="INFO"/>
                    </bean>
                    <bean class="net.ttddyy.dsproxy.listener.DataSourceQueryCountListener"/>
                </list>
            </property>
        </bean>
    </property>
</bean>

<alias name="proxyDataSource" alias="dataSource"/>

ตอนนี้เอาต์พุต Hibernate เทียบกับ datasource-proxy:

INFO  [main]: n.t.d.l.CommonsQueryLoggingListener - Name:, Time:1, Num:1, Query:{[select company0_.id as id1_6_, company0_.name as name2_6_ from Company company0_][]}
INFO  [main]: n.t.d.l.CommonsQueryLoggingListener - Name:, Time:0, Num:1, Query:{[insert into WarehouseProductInfo (id, quantity) values (default, ?)][19]}
INFO  [main]: n.t.d.l.CommonsQueryLoggingListener - Name:, Time:0, Num:1, Query:{[insert into Product (id, code, company_id, importer_id, name, version) values (default, ?, ?, ?, ?, ?)][phoneCode,1,-5,Phone,0]}

datasource-proxyแบบสอบถามประกอบด้วยค่าพารามิเตอร์และคุณยังสามารถเพิ่มคำสั่งไล่ JDBC ที่กำหนดเองเพื่อให้คุณสามารถจับ N + ปัญหาแบบสอบถาม 1 สิทธิ์จากการทดสอบการรวมของคุณ


5

เปิดorg.hibernate.typeLogger เพื่อดูว่าพารามิเตอร์จริงผูกกับเครื่องหมายคำถามอย่างไร


4

<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="logs/system.log" />
    <param name="Append" value="true" />
    <param name="ImmediateFlush" value="true" />
    <param name="MaxFileSize" value="200MB" />
    <param name="MaxBackupIndex" value="100" />

    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d %d{Z} [%t] %-5p (%F:%L) - %m%n" />
    </layout>
</appender>

<appender name="journaldev-hibernate" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="logs/project.log" />
    <param name="Append" value="true" />
    <param name="ImmediateFlush" value="true" />
    <param name="MaxFileSize" value="200MB" />
    <param name="MaxBackupIndex" value="50" />

    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d %d{Z} [%t] %-5p (%F:%L) - %m%n" />
    </layout>
</appender>

<logger name="com.journaldev.hibernate" additivity="false">
    <level value="DEBUG" />
    <appender-ref ref="journaldev-hibernate" />
</logger>

<logger name="org.hibernate" additivity="false">
    <level value="INFO" />
    <appender-ref ref="FILE" />
</logger>

<logger name="org.hibernate.type" additivity="false">
    <level value="TRACE" />
    <appender-ref ref="FILE" />
</logger>

<root>
    <priority value="INFO"></priority>
    <appender-ref ref="FILE" />
</root>


3

วิธีการแก้ปัญหานั้นถูกต้อง แต่บันทึกการเชื่อมโยงทั้งหมดสำหรับวัตถุผลลัพธ์ เพื่อป้องกันสิ่งนี้เป็นไปได้ที่จะสร้าง appender แยกต่างหากและเปิดใช้งานการกรองตัวอย่างเช่น

<!-- A time/date based rolling appender -->
<appender name="FILE_HIBERNATE" class="org.jboss.logging.appender.DailyRollingFileAppender">
    <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
    <param name="File" value="${jboss.server.log.dir}/hiber.log"/>
    <param name="Append" value="false"/>
    <param name="Threshold" value="TRACE"/>
    <!-- Rollover at midnight each day -->
    <param name="DatePattern" value="'.'yyyy-MM-dd"/>

    <layout class="org.apache.log4j.PatternLayout">
        <!-- The default pattern: Date Priority [Category] Message\n -->
        <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
    </layout>

    <filter class="org.apache.log4j.varia.StringMatchFilter">
        <param name="StringToMatch" value="bind" />
        <param name="AcceptOnMatch" value="true" />
    </filter>
    <filter class="org.apache.log4j.varia.StringMatchFilter">
        <param name="StringToMatch" value="select" />
        <param name="AcceptOnMatch" value="true" />
    </filter>  
    <filter class="org.apache.log4j.varia.DenyAllFilter"/>
</appender> 

<category name="org.hibernate.type">
  <priority value="TRACE"/>
</category>

<logger name="org.hibernate.type">
   <level value="TRACE"/> 
   <appender-ref ref="FILE_HIBERNATE"/>
</logger>

<logger name="org.hibernate.SQL">
   <level value="TRACE"/> 
   <appender-ref ref="FILE_HIBERNATE"/>
</logger>

3
**If you want hibernate to print generated sql queries with real values instead of question marks.**
**add following entry in hibernate.cfg.xml/hibernate.properties:**
show_sql=true
format_sql=true
use_sql_comments=true

**And add following entry in log4j.properties :**
log4j.logger.org.hibernate=INFO, hb
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE
log4j.appender.hb=org.apache.log4j.ConsoleAppender
log4j.appender.hb.layout=org.apache.log4j.PatternLayout

เฮ้เดียว 31 บรรทัดข้างต้นจะต้องมีการเพิ่มในไฟล์กำหนดค่าไฮเบอร์เนตของคุณแล้วมันจะทำงานได้อย่างแน่นอน ฉันมักจะโพสต์สิ่งที่ฉันได้ทำจริง
Vijay Bhatt

3

คำตอบนี้เป็นความแปรปรวนเล็กน้อยสำหรับคำถาม บางครั้งเราต้องการเพียง sql เท่านั้นสำหรับการดีบักในรันไทม์ ในกรณีนี้มีวิธีที่ง่ายกว่าโดยใช้การดีบักบนเครื่องมือแก้ไข

  • วางเบรกพอยต์บน org.hibernate.loader.Loader.loadEntityBatch (หรือไปที่สแต็กจนกระทั่งมี);
  • เมื่อการดำเนินการถูกระงับให้ดูค่าของตัวแปร this.sql;

นี่สำหรับไฮเบอร์เนต 3. ฉันไม่แน่ใจว่าจะใช้งานได้กับเวอร์ชันอื่น


3

ไดรเวอร์ mysql jdbc ได้จัดเตรียมความสะดวกเพื่อตอบสนองความต้องการนี้อย่างน้อยคุณต้องมีรุ่น jar> = mysql-connect-jar-5.1.6.jar

ขั้นตอนที่ 1: [กำหนดค่า jdbc.url ของคุณเพื่อเพิ่มตัวบันทึกและการบันทึกที่กำหนดเอง]

    jdbc.url=jdbc:mysql://host:port/your_db?logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true&profilerEventHandler=com.xxx.CustomLoggingProfilerEventHandler

ตอนนี้กำลังใช้การบันทึก slf4j หากการบันทึกเริ่มต้นของคุณคือ log4j คุณต้องเพิ่ม slf4j-api, slf4j-log4j12 dependencies เพื่อใช้การบันทึก slf4j

ขั้นตอนที่ 2: [เขียนบันทึกที่กำหนดเองของคุณ]

package com.xxx;
import java.sql.SQLException;
import java.util.Properties;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.log.Log;

public class CustomLoggingProfilerEventHandler implements ProfilerEventHandler {
    private Log log;

    public LoggingProfilerEventHandler() {
    }

    public void consumeEvent(ProfilerEvent evt) {
            /**
             * you can only print the sql as        this.log.logInfo(evt.getMessage())
             * you can adjust your sql print log level with: DEBUG,INFO
             * you can also handle the message to meet your requirement
             */ 
            this.log.logInfo(evt);
    }

    public void destroy() {
        this.log = null;
    }

    public void init(Connection conn, Properties props) throws SQLException {
        this.log = conn.getLog();
    }

}

2

ฉันชอบสิ่งนี้สำหรับ log4j:

log4j.logger.org.hibernate.SQL=trace
log4j.logger.org.hibernate.engine.query=trace
log4j.logger.org.hibernate.type=trace
log4j.logger.org.hibernate.jdbc=trace
log4j.logger.org.hibernate.type.descriptor.sql.BasicExtractor=error 
log4j.logger.org.hibernate.type.CollectionType=error 

เฮ้ - นี่ดีนะ แต่ฉันคิดว่านี่คำค้นหาจะถูกพิมพ์ด้วย? ตามด้วยค่าพารามิเตอร์ เนื่องจากฉันมีข้อความค้นหามากมายเหลือเกินฉันต้องการสิ่งที่ฉันสามารถคัดลอกวางบนตัวแก้ไข sql และพวกเขาจะถูกดำเนินการ มีวิธีที่ฉันสามารถทำได้โดยใช้วิธีนี้ ฉันไม่อยากไปห้องสมุดบุคคลที่สาม ขอบคุณ :)
dev ray

ขอบคุณ ฉันหวังว่าจะไม่ต้องใช้โซลูชันของบุคคลที่สามใด ๆ และจำศีลโดยตรง แต่ฉันคิดว่าฉันไม่มีทางเลือกอื่น
dev ray

2

การบันทึกใช้งานได้ แต่ไม่ตรงตามที่คุณต้องการหรือฉันต้องการเวลาก่อนหน้านี้ แต่P6Spyทำงานได้อย่างสมบูรณ์แบบ ,

นี่คือการสอนที่ง่ายต่อการใช้เช่นเดียวกับการสอน MKYONG สำหรับ P6SpyP6Spy

สำหรับฉันมันทำงานเหมือนมีเสน่ห์

  1. ดาวน์โหลดไลบรารี P6Spy

รับ“ p6spy-install.jar“

  1. แยกมันออกมา

แตกp6spy-install.jarไฟล์ค้นหาp6spy.jarและspy.properties

  1. เพิ่มการพึ่งพาไลบรารี

เพิ่มp6spy.jarในการพึ่งพาไลบรารีโครงการของคุณ

  1. แก้ไขไฟล์คุณสมบัติ P6Spy

แก้ไขไฟล์คอนฟิกูเรชันฐานข้อมูลของคุณ คุณต้องแทนที่ไดรเวอร์ JDBC ที่มีอยู่ด้วยไดรเวอร์ P6Spy JDBC -com.p6spy.engine.spy.P6SpyDriver

ต้นฉบับคือไดรเวอร์ MySQL JDBC - com.mysql.jdbc.Driver

<session-factory>
  <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
  <property name="hibernate.connection.password">password</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mkyong</property>
  <property name="hibernate.connection.username">root</property>
  <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
  <property name="show_sql">true</property>
</session-factory>

เปลี่ยนเป็นไดรเวอร์ P6Spy JDBC - com.p6spy.engine.spy.P6SpyDriver

<session-factory>
  <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
  <property name="hibernate.connection.driver_class">com.p6spy.engine.spy.P6SpyDriver
  </property>
  <property name="hibernate.connection.password">password</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mkyong</property>
  <property name="hibernate.connection.username">root</property>
  <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
  <property name="show_sql">true</property>
</session-factory>
  1. แก้ไขไฟล์คุณสมบัติ P6Spy แก้ไขไฟล์คุณสมบัติ P6Spy -spy.properties

แทนที่real driverด้วยไดรเวอร์ MySQL JDBC ที่มีอยู่ของคุณ

realdriver=com.mysql.jdbc.Driver

#specifies another driver to use
realdriver2=
#specifies a third driver to use
realdriver3=

เปลี่ยนตำแหน่งไฟล์บันทึกเปลี่ยนตำแหน่งไฟล์บันทึกในคุณสมบัติ logfile คำสั่ง SQL ทั้งหมดจะเข้าสู่ไฟล์นี้

ของ windows

logfile     = c:/spy.log

*ห้าม

logfile     = /srv/log/spy.log
  1. คัดลอก“spy.properties”ไปยัง classpath ของโครงการ

คัดลอก“spy.properties”ไปยังโฟลเดอร์รูทโปรเจคของคุณตรวจสอบให้แน่ใจว่าโปรเจ็กต์ของคุณสามารถค้นหา“ spy.properties” ได้มิฉะนั้น“spy.properties”ไฟล์จะแจ้งให้ไม่พบข้อยกเว้น


นี่เป็นเส้นทางที่ง่ายที่สุดสำหรับฉันในแอปพลิเคชัน Spring Boot ซึ่งฉันพยายามบันทึก SQL ที่สร้างจากการทดสอบหน่วย ฉันเพิ่มการพึ่งพาการทดสอบเป็น Gradle (testCompile 'p6spy: p6spy: 3.8.5'), application.yml ที่ปรับแล้วเพื่อตั้งค่า spring.datasource.url = jdbc: p6spy: h2: mem: testdb และ spring.datasource.driver-class- ชื่อ = com.p6spy.engine.spy.P6SpyDriver และเพิ่ม spy.properties ด้วย realdriver = org.h2.Driver และ logfile ให้ตั้งค่าเส้นทางที่ฉันต้องการ มันง่ายที่จะแยก SQL ที่สมบูรณ์ออกจากไฟล์บันทึกผลลัพธ์ อาการสะอึกเดียวคือ H2 ไม่ชอบรูปแบบการประทับเวลาที่สร้างขึ้น
Ken Pronovici

2

<appender name="console" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" 
      value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
    </layout>
</appender>

<logger name="org.hibernate" additivity="false">
    <level value="INFO" />
    <appender-ref ref="console" />
</logger>

<logger name="org.hibernate.type" additivity="false">
    <level value="TRACE" />
    <appender-ref ref="console" />
</logger>


สิ่งนี้เกี่ยวข้องกับคำถามได้อย่างไร
hotzst

2

ใช้ Hibernate 4 และ slf4j / log4j2 ฉันพยายามเพิ่มต่อไปนี้ในการกำหนดค่า log4j2.xml ของฉัน:

<Logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="trace" additivity="false"> 
    <AppenderRef ref="Console"/> 
</Logger> 
<Logger name="org.hibernate.type.EnumType" level="trace" additivity="false"> 
    <AppenderRef ref="Console"/>
</Logger>

แต่ไม่ประสบความสำเร็จ

ฉันค้นพบผ่านเธรดนี้ว่าเฟรมเวิร์กการบันทึกการทำงาน jboss ที่ใช้โดยไฮเบอร์เนตจำเป็นต้องถูกกำหนดค่าเพื่อล็อกอินผ่าน slf4j ฉันเพิ่มอาร์กิวเมนต์ต่อไปนี้ในอาร์กิวเมนต์ VM ของแอปพลิเคชัน:

-Dorg.jboss.logging.provider=slf4j

และมันก็ใช้งานได้เหมือนมีเสน่ห์


2

นี่คือสิ่งที่ใช้งานได้สำหรับฉันตั้งค่าคุณสมบัติด้านล่างใน log4j.file:

log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

การตั้งค่าคุณสมบัติไฮเบอร์เนต:

hibernate.show_sql=true

2

สำหรับการพัฒนาด้วย Wildfly (standalone.xml) ให้เพิ่มตัวบันทึกเหล่านั้น:

<logger category="org.hibernate.SQL">
   <level name="DEBUG"/>
</logger>
<logger category="org.hibernate.type.descriptor.sql">
   <level name="TRACE"/>
</logger>

1

ถ้าคุณใช้การจำศีล 3.2.xx ใช้

log4j.logger.org.hibernate.SQL=trace

แทน

log4j.logger.org.hibernate.SQL=debug 

1

คุณสามารถเข้าสู่ระบบนี้:

net.sf.hibernate.hql.QueryTranslator

ตัวอย่างผลลัพธ์:

2013-10-31 14:56:19,029 DEBUG [net.sf.hibernate.hql.QueryTranslator] HQL: select noti.id, noti.idmicrosite, noti.fcaducidad, noti.fpublicacion, noti.tipo, noti.imagen, noti.visible, trad.titulo, trad.subtitulo, trad.laurl, trad.urlnom, trad.fuente, trad.texto  from org.ibit.rol.sac.micromodel.Noticia noti join noti.traducciones trad where index(trad)='ca' and noti.visible='S' and noti.idmicrosite=985 and noti.tipo=3446

2013-10-31 14:56:19,029 DEBUG [net.sf.hibernate.hql.QueryTranslator] SQL: select noticia0_.NOT_CODI as x0_0_, noticia0_.NOT_MICCOD as x1_0_, noticia0_.NOT_CADUCA as x2_0_, noticia0_.NOT_PUBLIC as x3_0_, noticia0_.NOT_TIPO as x4_0_, noticia0_.NOT_IMAGEN as x5_0_, noticia0_.NOT_VISIB as x6_0_, traduccion1_.NID_TITULO as x7_0_, traduccion1_.NID_SUBTIT as x8_0_, traduccion1_.NID_URL as x9_0_, traduccion1_.NID_URLNOM as x10_0_, traduccion1_.NID_FUENTE as x11_0_, traduccion1_.NID_TEXTO as x12_0_ from GUS_NOTICS noticia0_ inner join GUS_NOTIDI traduccion1_ on noticia0_.NOT_CODI=traduccion1_.NID_NOTCOD where (traduccion1_.NID_CODIDI='ca' )and(noticia0_.NOT_VISIB='S' )and(noticia0_.NOT_MICCOD=985 )and(noticia0_.NOT_TIPO=3446 )

เฮ้ ... ฉันหาตัวอย่างของวิธีนี้ไม่ได้ คุณช่วยอ้างอิง / ตัวอย่าง / บทช่วยสอนได้ไหม และมันยังคงเหมือนเดิมกับรุ่นล่าสุดหรือ hibernate / log4j หรือกลายเป็น org.hibernate.QueryTranslator หรืออะไรบางอย่าง ขอบคุณ
dev ray

เฮ้ ... ฉันลองแล้ว แต่ดูเหมือนจะใช้งานไม่ได้กับบันทึกหรืออัปเดต ผมคิดว่ามันจะทำงานเฉพาะสำหรับการค้นหาเลือกที่แปลจากภาษา HQL กับ SQL เข้ามาในเล่น
ray dev

1

ปลั๊กอิน Log4Jdbc จะดีที่สุดสำหรับความต้องการของคุณ มันแสดงให้เห็นดังต่อไปนี้ -

1. Complete SQL query being hit to the db
2. Parameter values being passed to the query
3. Execution time taken by each query

อ้างอิงลิงค์ด้านล่างเพื่อกำหนดค่า Log4Jdbc-

https://code.google.com/p/log4jdbc/

1

ใช้Wiresharkหรืออะไรที่คล้ายกัน:

ไม่มีคำตอบดังกล่าวข้างต้นจะพิมพ์ sql กับพารามิเตอร์อย่างถูกต้องหรือเป็นความเจ็บปวด ฉันประสบความสำเร็จโดยใช้WireSharkซึ่งจับ sql / คำสั่งทั้งหมดที่ถูกส่งจากแอปพลิเคชันไปยัง Oracle / Mysql และอื่น ๆ ด้วยคำสั่ง


2
Log4JDBC จะ ดูด้านบน.
Alan Hay

1

คำตอบทั้งหมดที่นี่มีประโยชน์ แต่ถ้าคุณกำลังใช้ XML แอปพลิเคชันบริบทของ Spring เพื่อตั้งค่าโรงงานเซสชันของคุณการตั้งค่าตัวแปรระดับ log4j SQL จะทำให้คุณได้เป็นส่วนหนึ่งของวิธีที่นั่นคุณต้องตั้งค่าตัวแปร hibernate.show_sql ในบริบทของแอพเพื่อให้ Hibernate เริ่มแสดงค่าได้จริง

ApplicationContext.xml มี:

<property name="hibernateProperties">
            <value>
            hibernate.jdbc.batch_size=25
            ... <!-- Other parameter values here -->
            hibernate.show_sql=true
            </value>
 </property>

และไฟล์ log4j ของคุณต้องการ

log4j.logger.org.hibernate.SQL=DEBUG

1

ใน Java:

แปลงคิวรีของคุณใน TypedQuery หากเป็น CriteriaQuery (javax.persistence)

แล้ว:

query.unwrap (org.hibernate.Query.class) .getQueryString ();


1
ขอบคุณมันพิมพ์คิวรี่ แต่ไม่ใช่พารามิเตอร์ที่ใช้มีวิธีพิมพ์พารามิเตอร์ด้วยหรือไม่
Liz Lamperouge

0

Hibernate แสดงแบบสอบถามและค่าพารามิเตอร์ในบรรทัดที่แตกต่างกัน

หากคุณใช้ application.properties ใน spring boot และคุณสามารถใช้พารามิเตอร์ที่ไฮไลต์ด้านล่างใน application.properties

  1. org.hibernate.SQL จะแสดงข้อความค้นหา

    logging.level.org.hibernate.SQL = DEBUG

  2. org.hibernate.type จะแสดงค่าพารามิเตอร์ทั้งหมดซึ่งจะจับคู่กับการเลือกแทรกและอัปเดตแบบสอบถาม logging.level.org.hibernate.type = TRACE

    • org.hibernate.type.EnumType จะแสดงค่าพารามิเตอร์ประเภท enum

      logging.level.org.hibernate.type.EnumType = TRACE

      ตัวอย่าง ::

      2018-06-14 11:06:28,217 TRACE [main] [EnumType.java : 321] Binding [active] to parameter: [1]
    • sql.BasicBinder จะแสดงค่าพารามิเตอร์จำนวนเต็ม, varchar, บูลีน

      logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE

      ตัวอย่าง ::

      • 2018-06-14 11: 28: 29,750 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] พารามิเตอร์การผูก [1] เป็น [บูลีน] - [จริง]
      • 2018-06-14 11: 28: 29,751 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] พารามิเตอร์การรวม [2] เป็น [INTEGER] - [1]
      • 2018-06-14 11: 28: 29,752 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] พารามิเตอร์การผูก [3] เป็น [VARCHAR] - [สาธารณะ]

1
แม้จะไม่แสดงค่าสำหรับการจำกัดและการหักล้างในแบบสอบถาม
T3rm1

0

ทางออกที่ง่ายที่สุดสำหรับฉันคือการใช้ stringReplace ปกติเพื่อแทนที่อินพุตพารามิเตอร์ด้วยค่าพารามิเตอร์ (การปฏิบัติต่อพารามิเตอร์ทั้งหมดเป็นสตริงเพื่อความเรียบง่าย):

 String debugedSql = sql;
 //then, for each named parameter
     debugedSql = debugedSql.replaceAll(":"+key, "'"+value.toString()+"'");
 //and finnaly
 println(debugedSql);

หรือบางอย่างที่คล้ายกันสำหรับพารามิเตอร์ตำแหน่ง (?)
ดูแลค่า Null และชนิดของค่าเฉพาะเช่นวันที่หากคุณต้องการให้ sql ที่พร้อมใช้งานถูกบันทึก

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