如何查看JPA发出的SQL查询?


155

当我的代码发出这样的调用时:

entityManager.find(Customer.class, customerID);

如何查看此调用的SQL查询?假设我无权访问数据库服务器来分析/监视调用,是否可以在IDE中记录或查看JPA调用发出的相应SQL查询?我要使用jTDS驱动程序反对SQL Server 2008 R2。


8
什么是JPA提供程序?我相信此设置是特定于提供程序的。
btiernay 2010年

@Sajee,请问您能否将axtavt的答案标记为已接受,以便将访问者的问题直接引向该答案?
8bitjunkie

Answers:


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.Native为一个级别,例如DEBUG


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 2012年

另外,似乎<properties>节点需要位于<persistence-unit>中其他所有元素的下面。<3 XML。
Tom Spurling 2014年

1
这些属性应在哪里设置?
亚历克斯·沃登

34

另外,如果您使用的是EclipseLink,并且希望输出SQL参数值,则可以将此属性添加到persistence.xml文件中:

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

是否有其他方法可以获取intellij中的绑定值?
维尼修斯中号

15

如果您使用休眠和注销作为记录器,则可以使用以下内容(仅显示绑定而不显示结果):

<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打印查询

<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时,可以使用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 2012年

1
Record参数是包含查询参数的(Record,XMLRecord)之一
Tomasz

如果我有类似Query的查询myQuery = EntityManager.createNamedQuery(“ MyEntity.findMe”); myQuery.setParameter(“ param1”,“ someValue);如何从myQuery获取recordWithValues?
zmeda 2012年

更新了我的答案以包括recordWithValues创建。
Tomasz 2012年

嘿,您知道如何针对未与JPA一起运行的eclipseLink废话执行此操作吗?(我什至不知道它到底是什么,但是它已经从工作台应用程序中生成了映射类...。但是,我没有EM,但是只有toplink Service可以请求Session,但是不知道任何查询。我使用诸如ReadAllQuery,ExpressionBuilder和Expression之类的类。如果它不太清楚,您不需要答复(我不是专业人士,我习惯于JPA),我将在接下来的48小时内删除此评论,并尝试提出更清晰的问题;)
JBA 2013年

7

为了查看OpenJPA中的所有SQL和参数,请将这两个参数放在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 2014年

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框架。如下修改您的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

在探索性开发过程中,为了将SQL调试日志记录集中在要检查的特定方法上,我用以下logger语句装饰了该方法:

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);

0

EclipseLink输出SQL(persistence.xml配置):

<property name="eclipselink.logging.level.sql" value="FINE" />

-2

有一个名为persistence.xml的文件。按Ctrl + Shift + R并找到它,然后在某个地方编写了类似showSQL的内容。

只是说真的

我不确定服务器是否必须以调试模式启动。检查在控制台上创建的SQL。


这还不足以显示sql语句仅显示参数吗?用于参数。
Ebuzer Taha KANAT

1
“ showSQL之类的东西”没有答案。和Ctrl + Shift + R?您已经对IDE进行了假设。
8bitjunkie
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.