วิธีดูแบบสอบถาม SQL ที่ออกโดย JPA


155

เมื่อรหัสของฉันโทรออกเช่นนี้:

entityManager.find(Customer.class, customerID);

ฉันจะดูแบบสอบถาม SQL สำหรับการโทรนี้ได้อย่างไร สมมติว่าฉันไม่มีสิทธิ์เข้าถึงเซิร์ฟเวอร์ฐานข้อมูลเพื่อทำโปรไฟล์ / ตรวจสอบการโทรมีวิธีบันทึกหรือดูภายใน IDE ของฉันเกี่ยวกับการสืบค้น SQL ที่สอดคล้องกันที่ออกโดยการเรียก JPA หรือไม่ ฉันใช้ SQL Server 2008 R2 กับไดรเวอร์ jTDS


8
ผู้ให้บริการ JPA คืออะไร ฉันเชื่อว่าการตั้งค่านี้เฉพาะผู้ให้บริการ
btiernay

@Sajee ได้โปรดทำเครื่องหมายคำตอบของ axtavt ว่ายอมรับแล้วเพื่อให้ผู้เข้าชมตอบคำถามของคุณตรงกับคำตอบนี้หรือไม่?
8bitjunkie

คำตอบ:


332

ตัวเลือกการบันทึกเป็นข้อมูลเฉพาะของผู้ให้บริการ คุณต้องรู้ว่าการใช้ JPA แบบใดที่คุณใช้

  • ไฮเบอร์เนต ( ดูที่นี่ ):

    <property name = "hibernate.show_sql" value = "true" />
  • EclipseLink ( ดูที่นี่ ):

    <property name="eclipselink.logging.level" value="FINE"/>
  • OpenJPA ( ดูที่นี่ ):

    <property name="openjpa.Log" value="DefaultLevel=WARN,Runtime=INFO,Tool=INFO,SQL=TRACE"/>
  • DataNucleus ( ดูที่นี่ ):

    ตั้งค่ารายการบันทึกในระดับเช่นDataNucleus.Datastore.NativeDEBUG


4
@Sajee: คุณควรให้เครื่องหมายถูกเพื่อตอบว่าเป็นคำตอบที่ยอมรับได้ มันใช้งานได้ดีสำหรับฉันโดยใช้ Hibernate หากคุณเห็นด้วยกับคำตอบนี้คุณและผู้ตอบจะได้รับคะแนนมากขึ้นและได้รับอนุญาตมากขึ้นใน stackoverflow.com
LS

57
คุณจะวางบรรทัดนี้ใน persistence.xml ของคุณสำหรับเนื้อหาใด ๆ ที่เป็นเส้นโค้ง มันจะอยู่ภายใต้โหนด <properties> ... ขออภัยถ้าเห็นได้ชัดว่าฉันสับสนว่าจะใส่ไว้ที่ไหน
SoftwareSavant

5
เมื่อใช้ Hibernate และ log4j คุณสามารถตั้งค่าตัวบันทึก "org.hibernate.SQL" เป็น DEBUG ( javalobby.org/java/forums/t44119.html )
MosheElisha

นอกจากนี้ดูเหมือนว่าโหนด <properties> จะต้องอยู่ภายใต้สิ่งอื่นใดภายใน <persistence-unit> <3 XML
Tom Spurling

1
คุณสมบัติเหล่านี้ควรตั้งอยู่ที่ไหน?
Alex Worden

34

นอกจากนี้หากคุณใช้ EclipseLink และต้องการส่งออกค่าพารามิเตอร์ SQL คุณสามารถเพิ่มคุณสมบัตินี้ไปยังไฟล์ persistence.xml ของคุณ:

<property name="eclipselink.logging.parameters" value="true"/>

มีทางเลือกอื่นในการรับค่าการผูกใน Intellij หรือไม่?
Vinícius M

15

หากคุณใช้ hibernate และ logback เป็นคนตัดไม้คุณสามารถใช้สิ่งต่อไปนี้ (แสดงการเชื่อมเท่านั้นไม่ใช่ผลลัพธ์):

<appender
    name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -
            %msg%n</pattern>
    </encoder>
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
        <evaluator>
            <expression>return message.toLowerCase().contains("org.hibernate.type") &amp;&amp;
                logger.startsWith("returning");</expression>
        </evaluator>
        <OnMismatch>NEUTRAL</OnMismatch>
        <OnMatch>DENY</OnMatch>
    </filter>
</appender>

org.hibernate.SQL = DEBUGพิมพ์ Query

<logger name="org.hibernate.SQL">
    <level value="DEBUG" />
</logger>

org.hibernate.type = TRACEพิมพ์การเชื่อมและโดยปกติผลลัพธ์ซึ่งจะถูกระงับผ่านตัวกรองที่กำหนดเอง

<logger name="org.hibernate.type">
    <level value="TRACE" />
</logger>

คุณต้องพึ่งพา janino (http://logback.qos.ch/manual/filters.html#JaninoEventEvaluator):

<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>2.6.1</version>
</dependency>

15

ใน EclipseLink เพื่อรับ SQL สำหรับ Query เฉพาะตอนรันไทม์คุณสามารถใช้ DatabaseQuery API:

Query query = em.createNamedQuery("findMe"); 
Session session = em.unwrap(JpaEntityManager.class).getActiveSession(); 
DatabaseQuery databaseQuery = ((EJBQueryImpl)query).getDatabaseQuery(); 
databaseQuery.prepareCall(session, new DatabaseRecord());

String sqlString = databaseQuery.getSQLString();

SQL นี้จะมี? สำหรับพารามิเตอร์ ในการรับ SQL แปลด้วยอาร์กิวเมนต์คุณต้องใช้ DatabaseRecord พร้อมค่าพารามิเตอร์

DatabaseRecord recordWithValues= new DatabaseRecord();
recordWithValues.add(new DatabaseField("param1"), "someValue");

String sqlStringWithArgs = 
         databaseQuery.getTranslatedSQLString(session, recordWithValues);

ที่มา: วิธีรับ SQL สำหรับการสืบค้น


RecordWithValues ​​คืออะไร เป็นไปได้ที่จะได้รับจาก DatabaseQuery หรือ EJBQueryImpl?
zmeda

1
อาร์กิวเมนต์ Record เป็นหนึ่งใน (Record, XMLRecord) ที่มีอาร์กิวเมนต์ของการสืบค้น
Tomasz

ถ้าฉันมีบางอย่างเช่น Query myQuery = entityManager.createNamedQuery ("MyEntity.findMe"); myQuery.setParameter ("param1", "someValue); วิธีการรับ recordWithVues จาก myQuery?
zmeda

อัปเดตคำตอบของฉันเพื่อรวมการบันทึกด้วยการสร้างค่า
Tomasz

คุณรู้วิธีการทำเช่นนี้สำหรับ eclipseLink crap ที่ไม่ได้ทำงานกับ JPA หรือไม่ (ฉันไม่รู้ด้วยซ้ำว่ามันคืออะไร แต่สร้างการแมปคลาสจากแอ็พพลิเคชัน workbench .... อย่างไรก็ตามฉันไม่ได้ใช้ EM แต่เป็นบริการของ toplink เท่านั้นฉันสามารถขอเซสชันได้ แต่ไม่ทราบคำถามใด ๆ ฉัน ใช้คลาสเช่น ReadAllQuery, ExpressionBuilder และ Expression คุณไม่จำเป็นต้องตอบกลับหากมันไม่ชัดเจน (ฉันไม่ใช่มืออาชีพในเรื่องนี้ฉันเคยใช้ JPA) ฉันจะลบความคิดเห็นนี้ภายใน 48 ชั่วโมงถัดไปและลองถามคำถามที่ชัดเจนกว่า)
JBA

7

ในการดู SQL และพารามิเตอร์ทั้งหมดใน OpenJPA ให้ใส่พารามิเตอร์ทั้งสองนี้ใน persistence.xml:

<property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
<property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />

5

หากคุณต้องการดูข้อความค้นหาที่แน่นอนพร้อมกับค่าพารามิเตอร์และค่าส่งคืนคุณสามารถใช้ไดรเวอร์พร็อกซี jdbc มันจะขัดขวางการเรียก jdbc ทั้งหมดและบันทึกค่าของพวกเขา ผู้รับมอบฉันทะบางส่วน:

  • log4jdbc
  • jdbcspy

พวกเขาอาจมีคุณสมบัติเพิ่มเติมบางอย่างเช่นการวัดเวลาดำเนินการสำหรับแบบสอบถามและรวบรวมสถิติ


4

ตัวอย่างการใช้ log4j ( src \ log4j.xml ):

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

<appender name="CA" class="org.apache.log4j.AsyncAppender">
    <param name="BufferSize" value="512"/>
    <appender-ref ref="CA_OUTPUT"/>
</appender>
<appender name="CA_OUTPUT" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="[%p] %d %c %M - %m%n"/>
    </layout>
</appender>

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

<root>
    <level value="WARN"/>
    <appender-ref ref="CA"/>
</root>


1
โปรดอธิบายคำตอบของคุณอีกเล็กน้อย ฉันคิดว่าส่วนหลักคือส่วน org.hibernate.SQL?
JackDev

2

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

พิมพ์คำสั่ง SQL เพื่อทำการพิมพ์มาตรฐานโดยไม่มีพารามิเตอร์ของคำสั่งที่เตรียมไว้และไม่มีการปรับปรุงกรอบการบันทึก :

application.properties ไฟล์:

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

application.yml ไฟล์:

spring:
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true

พิมพ์คำสั่ง SQL ที่ใช้งานง่ายพร้อมพารามิเตอร์ของคำสั่งที่เตรียมไว้โดยใช้เฟรมเวิร์กการบันทึก :

application.properties ไฟล์:

spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

application.yml ไฟล์:

spring:
  jpa:
    properties:
      hibernate:
        format_sql: true
logging:
  level:
    org:
      hibernate:
        SQL: DEBUG
        type:
          descriptor:
            sql:
              BasicBinder: TRACE

พิมพ์คิวรี SQL ที่ไม่มีพารามิเตอร์ของคำสั่งที่เตรียมไว้โดยใช้เฟรมเวิร์กการบันทึก :

application.properties ไฟล์:

spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG

application.yml ไฟล์:

spring:
  jpa:
    properties:
      hibernate:
        format_sql: true
logging:
  level:
    org:
      hibernate:
        SQL: DEBUG

ที่มา (และรายละเอียดเพิ่มเติม): https://www.baeldung.com/sql-logging-spring-boot


1

นอกจากนี้หากใช้ WildFly / JBoss ให้ตั้งค่าระดับการบันทึกของ org.hibernate เป็น DEBUG

ไฮเบอร์เนตเข้าสู่ระบบใน WildFly


1

ตัวเลือกที่ดีอีกอย่างหนึ่งถ้าคุณมีบันทึกมากเกินไปและคุณต้องการวางไว้ชั่วคราวSystem.out.println()เท่านั้นคุณสามารถทำได้โดยขึ้นอยู่กับผู้ให้บริการของคุณ:

CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<ExaminationType> criteriaQuery = criteriaBuilder.createQuery(getEntityClass()); 

/* For Hibernate */
System.out.println(getEntityManager().createQuery(criteriaQuery).unwrap(org.hibernate.Query.class).getQueryString());

/* For OpenJPA */ 
System.out.println(getEntityManager().createQuery(criteriaQuery).unwrap(org.apache.openjpa.persistence.QueryImpl.class).getQueryString());

/* For EclipseLink */
System.out.println(getEntityManager().createQuery(criteriaQuery).unwrap(JpaQuery.class).getSQLString());

ในการใช้งาน openjpa ของเราสิ่งนี้จะไม่แสดงพารามิเตอร์เป็นส่วนหนึ่งของการสืบค้นสำหรับการสืบค้นแบบพารามิเตอร์
timwaagh

1

หากคุณใช้ Spring Framework แก้ไขไฟล์application.propertiesของคุณดังต่อไปนี้

#Logging JPA Queries, 1st line Log Query. 2nd line Log parameters of prepared statements 
logging.level.org.hibernate.SQL=DEBUG  
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE  

#Logging JdbcTemplate Queries, 1st line Log Query. 2nd line Log parameters of prepared statements 
logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG  
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE  

0

ฉันไม่ได้ใช้ไฮเบอร์เนต AFAIK JPA ธรรมดา ๆ showSQL ดูเหมือนว่าคุณสมบัติไฮเบอร์เนต มันจะใช้งานได้ในกรณีของฉันหรือไม่
Sajee

ดูเหมือนว่าคำตอบคือไม่ฉันไม่เห็น SQL ในบันทึก
Sajee

1
สวัสดี, คุณจะประกาศคุณสมบัติใน persistence.xml ของคุณได้อย่างไร?
Gondim

0

ด้วย Spring Boot เพียงเพิ่ม: spring.jpa.show-sql = true ไปยัง application.properties สิ่งนี้จะแสดงข้อความค้นหา แต่ไม่มีพารามิเตอร์จริง (คุณจะเห็นแทนที่จะเป็นแต่ละพารามิเตอร์)


0

ระหว่างการพัฒนาเชิงสำรวจและเพื่อมุ่งเน้นการบันทึกการดีบัก SQL ในวิธีการเฉพาะที่ฉันต้องการตรวจสอบฉันตกแต่งวิธีนั้นด้วยคำสั่งตัวบันทึกต่อไปนี้:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;

((ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.hibernate.SQL")).setLevel(Level.DEBUG);
entityManager.find(Customer.class, customerID);
((ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.hibernate.SQL")).setLevel(Level.INFO);


-2

มีไฟล์ชื่อ persistence.xml กด Ctrl + Shift + R แล้วค้นหาจากนั้นก็จะมีที่สำหรับเขียนเช่น showSQL

เพียงแค่ใส่เป็นความจริง

ฉันไม่แน่ใจว่าเซิร์ฟเวอร์จะต้องเริ่มต้นเป็นโหมดดีบั๊กหรือไม่ ตรวจสอบ SQL ที่สร้างขึ้นบนคอนโซล


นี้ไม่เพียงพอที่จะแสดงพารามิเตอร์คำสั่ง sql แสดงเท่านั้น สำหรับพารามิเตอร์
Ebuzer Taha KANAT

1
"Something like showSQL" ไม่ได้รับคำตอบ และ Ctrl + Shift + R? คุณได้ตั้งสมมติฐานเกี่ยวกับ IDE แล้ว
8bitjunkie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.