ChatGPT解决这个技术问题 Extra ChatGPT

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

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

entityManager.find(Customer.class, customerID);

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

什么是 JPA 提供程序?我相信此设置是特定于提供商的。
@Sajee,您能否将 axtavt 的答案标记为已接受,以便将访问者直接引导至您的问题?

z
zb226

日志记录选项是特定于提供商的。您需要知道您使用的是哪种 JPA 实现。

Hibernate(见这里):

EclipseLink(见这里):

OpenJPA(参见此处):

DataNucleus(参见此处):将日志类别 DataNucleus.Datastore.Native 设置为一个级别,例如 DEBUG。


@Sajee:您应该勾选这个答案,以表明这是已接受的答案。使用 Hibernate 对我来说效果很好。如果您同意此答案,您和回答者将在 stackoverflow.com 上获得更多积分和更多权限。
对于任何好奇的主体,您都可以将这一行放在您的 persistence.xml 中。它将在 节点下...对不起,如果这很明显,我只是对自己放置它的位置感到困惑。
使用 Hibernate 和 log4j 时,您还可以将“org.hibernate.SQL”记录器设置为 DEBUG (javalobby.org/java/forums/t44119.html)
此外,似乎 节点需要位于 中的所有其他内容之下。 <3 XML。
这些属性应该在哪里设置?
T
ThePizzle

此外,如果您正在使用 EclipseLink 并且想要输出 SQL 参数值,您可以将此属性添加到您的 persistence.xml 文件中:

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

是否有替代方法可以在 intellij 中获取绑定值?
K
Kuhpid

如果您使用 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 打印查询

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

T
Tomasz

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

来源:How to get the SQL for a Query


什么是recordWithValues?是否可以从 DatabaseQuery 或 EJBQueryImpl 获得它?
Record 参数是包含查询参数的 (Record, XMLRecord) 之一
如果我有类似 Query myQuery = entityManager.createNamedQuery("MyEntity.findMe"); myQuery.setParameter("param1", "someValue); 如何从 myQuery 中获取 recordWithValues?
更新了我的答案以包括 recordWithValues 创建。
嘿,您知道如何为未使用 JPA 运行的 eclipseLink 废话执行此操作吗? (我什至不知道它到底是什么,但它已经从工作台应用程序生成了映射类......但是我没有 EM,但只有一个 toplink 服务我可以请求一个会话但不知道任何查询。我使用 ReadAllQuery、ExpressionBuilder 和 Expression 等类。如果它太不清楚,您不需要回复(我不是这方面的专业人士,我已经习惯了 JPA)我将在接下来的 48 小时内删除此评论并尝试提出更清晰的问题;)
K
Kent Munthe Caspersen

我制作了一份我认为对其他人有用的备忘单。在所有示例中,如果您想将记录的查询保留在一行中(没有漂亮的打印),您可以删除 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


j
jfcorugedo

为了查看 OpenJPA 中的所有 SQL 和参数,将这两个参数放在 persistence.xml 中:

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

m
mateusz.fiolka

如果您想查看带有参数值和返回值的确切查询,您可以使用 jdbc 代理驱动程序。它将拦截所有 jdbc 调用并记录它们的值。一些代理:

log4jdbc

jdbcspy

它们还可能提供一些附加功能,例如测量查询的执行时间和收集统计信息。


M
Marcus Becker

使用 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>


请多解释一下你的答案。我假设主要部分是 org.hibernate.SQL 部分?
S
Strinder

另一个 good option 如果您有太多日志并且只想将其作为临时 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.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 的实现中,这不会将参数显示为参数化查询的查询的一部分。
a
agelbess

此外,如果使用 WildFly/JBoss,请将 org.hibernate 的日志记录级别设置为 DEBUG

https://i.stack.imgur.com/cV0mR.png


t
thyzz

如果您使用的是 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  

C
Community

请参阅Can't make hibernate stop showing SQL using Spring JPA Vendor Adapter


我没有使用休眠。 AFAIK,只是普通的旧 JPA。 showSQL 看起来像一个 Hibernate 属性。这对我有用吗?
看起来答案是否定的。我在日志中看不到任何 SQL。
Sajee,你如何在persistence.xml 上声明属性?
E
Elhanan Mishraky

使用 Spring Boot,只需将 spring.jpa.show-sql=true 添加到 application.properties。这将显示查询但没有实际参数(您将看到 ? 而不是每个参数)。


A
Abdull

在探索性开发期间,为了将 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);


C
CamelTM

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

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

P
Prashant S

JPA 提供者可以为您设置 - 如果有人不想通过 JPA 属性进行控制

public static JpaProperties properties() {
        final JpaProperties jpaProperties = new JpaProperties();
        jpaProperties.setShowSql(true);

p
pete

对于需要从 javax.persistence.Query 验证 SQL 的任何人

    import org.hibernate.query.Query;

    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.Assertions;

    import javax.enterprise.context.RequestScoped;
    import javax.inject.Inject;
    import javax.persistence.EntityManager;
    import javax.persistence.Query;

    @RequestScoped
    public class QueryServices {

       @Inject
       protected EntityManager entityManager;

       public Query buildQuery(String searchCriteria) {
          return entityManager.createNativeQuery("select * from table t where t.animal = ?1"))
          .setParameter(1, searchCriteria);
       }
       

    class QueryServicesTest {
       @Test
       void buildQuerySqlGenerationTest() {
          final String searchFor = "cat"; 

          // Build a query object to check
          org.hibernate.query.Query query = workflowServices.buildQuery(searchFor)
                .unwrap(org.hibernate.query.Query.class).getQueryString();

          // Validate the generated sql contains the search value
          Assertions.assertTrue(query.contains(searchFor);
       }
    }

G
Gondim

有一个文件叫persistence.xml 按Ctrl+Shift+R 找到,然后,有个地方写了showSQL之类的东西。

把它当作真的

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


这还不足以显示参数sql语句只显示?为参数。
“类似 showSQL 的东西”不是答案。和 Ctrl + Shift + R?您已经对 IDE 做出了假设。