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

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

entityManager.find(Customer.class, customerID);

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

307473 次浏览

有一个文件,名为恒存. xml 按下 Ctrl + Shift + R 找到它,然后,就会出现一个写有 showSQL 之类内容的地方。

就当是真的吧

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

日志记录选项是特定于提供程序的。

  • Hibernate (看这里) :

    <property name = "hibernate.show_sql" value = "true" />
    
  • EclipseLink (see here):

    <property name="eclipselink.logging.level" value="FINE"/>
    
  • OpenJPA (see here):

    <property name="openjpa.Log" value="DefaultLevel=WARN,Runtime=INFO,Tool=INFO,SQL=TRACE"/>
    
  • DataNucleus (see here):

    Set the log category DataNucleus.Datastore.Native to a level, like DEBUG.

另外,如果您正在使用 EclipseLink 并希望输出 SQL 参数值,那么可以将这个属性添加到尾声文件:

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

在 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

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

SQL = DEBUG 打印查询

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

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>

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

  • Log4jdbc
  • Jdbc 间谍

它们还可以提供一些额外的特性,比如测量查询的执行时间和收集统计信息。

为了查看 OpenJPA 中的所有 SQL 和参数,请将这两个参数放入尾端的尾端.xml 文件中:

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

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

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

Hibernate Logging in WildFly

另一个 不错的选择如果你有太多的日志,你只想把作为一个时态 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());

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

如果您使用的是 Spring 框架,请按如下方式修改您的 < em > 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

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


我做了一个小抄,我认为可以对其他人有用。在所有示例中,如果希望将记录的查询保留在一行中(没有漂亮的打印) ,则可以删除 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

EclipseLink 输出 SQL (尾声.xml 配置文件) :

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

JPA 提供程序可以为您设置它——如果有人不想通过 JPA 属性进行控制的话

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

对于任何需要验证来自 javax.restence.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);
}
}

我们也可以通过结构化方式查看 sql,方法是将这些属性添加到 应用性能

spring.h2.console.enabled=true
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type=trace