在Hibernate中是否有可能用真实值而不是问号打印生成的SQL查询?
如果无法使用Hibernate API,您会建议如何使用实际值打印查询?
在Hibernate中是否有可能用真实值而不是问号打印生成的SQL查询?
如果无法使用Hibernate API,您会建议如何使用实际值打印查询?
当前回答
日志可以工作,但并不是您想要的,但P6Spy可以完美地工作。
这里有一个简单的教程来实现以及。对我来说,这就像魅力。
下载P6Spy库:获取P6Spy -install.jar 解压:解压p6spy-install.jar文件,查找p6spy.jar和spy.properties 添加库依赖项:将p6spy.jar添加到项目库依赖项中 Modify P6Spy properties file:修改数据库配置文件。您需要用P6Spy JDBC驱动程序替换现有的JDBC驱动程序。
原来是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> <!-- note the difference -->
<property name="hibernate.connection.password">password</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/myuser</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> <!-- note the difference -->
<property name="hibernate.connection.password">password</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/myuser</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属性文件:spy.properties
用现有的MySQL JDBC驱动程序替换realdriver
realdriver=com.mysql.jdbc.Driver
# specifies another driver to use
realdriver2=
# specifies a third driver to use
realdriver3=
在logfile属性中更改日志文件的位置。所有SQL语句都将被记录到这个文件中。
窗口:
logfile=c:/spy.log
UNIX:
logfile=/srv/log/spy.log
复制的间谍。属性到项目类路径:复制间谍。属性添加到项目根文件夹。确保你的项目可以定位间谍。财产,否则就是间谍。属性文件未找到异常将被抛出。
其他回答
Hibernate在不同的行中显示查询及其参数值。
如果你正在使用应用程序。你可以在application.properties中使用下面突出显示的参数。
org.hibernate.SQL will show queries: logging.level.org.hibernate.SQL=DEBUG org.hibernate.type will show all parameter values, which will map with select, insert and update queries. logging.level.org.hibernate.type=TRACE org.hibernate.type.EnumType will show enum type parameter value: logging.level.org.hibernate.type.EnumType=TRACE Example output: 2018-06-14 11:06:28,217 TRACE [main] [EnumType.java : 321] Binding [active] to parameter: [1] sql.BasicBinder will show integer, varchar, boolean type parameter value logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE Example output: * 2018-06-14 11:28:29,750 TRACE [http-nio-9891-exec-2] [BasicBinder.java : 65] binding parameter [1] as [BOOLEAN] - [true] * 2018-06-14 11:28:29,751 TRACE [http-nio-9891-exec-2] [BasicBinder.java : 65] binding parameter [2] as [INTEGER] - [1] * 2018-06-14 11:28:29,752 TRACE [http-nio-9891-exec-2] [BasicBinder.java : 65] binding parameter [3] as [VARCHAR] - [public]
正如我在这篇文章中所描述的,您可以使用数据源-代理来实现。
假设你的应用程序需要一个dataSource bean(例如通过@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输出vs.数据源-代理:
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]}
数据源-代理查询包含参数值,您甚至可以添加自定义JDBC语句拦截器,以便从集成测试中捕获N+1个查询问题。
使用YAML属性:
logging.level.org.hibernate:
SQL: DEBUG
type.descriptor.sql.BasicBinder: TRACE
使用Wireshark或类似的工具:
上面提到的答案都不会正确地打印带参数的SQL,或者让它与它们一起工作是一件痛苦的事情。我通过使用WireShark实现了这一点,它可以捕获从应用程序发送到Oracle/MySQL等的所有SQL/命令。
您需要为以下类别启用日志记录:
SQL -设置为调试,以便在执行所有SQL DML语句时记录日志 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
第一种方法相当于冬眠。Show_sql =true遗留属性时,第二个函数将打印绑定的参数。
另一种解决方案(非基于hibernate)是使用像P6Spy这样的JDBC代理驱动程序。