springboot输出最终sql
在实际开发过程中,如果选择了springboot+jpa的⽅式,那么和数据库的交互⽅式就被框架层'过度'封装,别误会,这⾥的过度封装没有贬义,只是个⼈⽔平有限,在翻阅hibernate以及jpa相关源码时,有点⼀头雾⽔,折腾蛮久,就是没定位到sql最终在数据库中执⾏的形式,⼤多数场景下,yml配置中配置
jpa:
show-sql: true
或者
logging:
level:
springboot切换log4j2
org:
hibernate:
type.descriptor.sql.BasicBinder: trace
SQL: debug
这两种形式可以在控制台中输出预执⾏sql和参数,通过⾃⼰替换占位参数也能拼出来sql。⼤多数场景也就可以满⾜⽇常调试需求。
记⼀次我遇到的场景。
循环执⾏⼀条查询sql,发现第⼆批sql始终返回为空,观察控制台打印的sql,将sql拼上去拿到数据库中执⾏发现可以查到数据,但是代码层⾯始终返回为空。
处理成的sql如下:
SELECT ss.* FROM sim_signal_schedules ss WHERE ss.data_source = 2  AND ss.last_updated_date >= 'Mon Oct 25 11:03:26 CST 2021'
and ss.schedule_id in ( 'b77b8df3-3272-4da3-9ff6-34fedc3ac823','bdf45c6e-47ed-44aa-b385-d5f04fe6cab0','d34878f9-fa12-4d17-bea1-45a37fc9eaa7');
时间 Mon Oct 25 11:03:26 CST 2021是完全copy控制台输出的⼊参,in()⾥⾯的参数也是,数据库中通过这条sql确实有数据。
尝试解决的思路有:
  1. 怀疑参数中存在特殊字符导致编码导致的(其实我这⾥不存在中⽂和⼀些特殊字符,关键问题是我for循环调⽤,前⾯已经有执⾏成功的iteration)
  2. 怀疑jpa中sql书写的⽅式导致(虽然不想排查这个,因为还是存在成功的查询,没法解释)
  3. sql最终的执⾏形态
最后发现有效的解决⽅案是3,通过修改配置,输出了jdbc最终的执⾏sql,发现是jpa中输出参数的binder对时间类型的数据类型的表达和数据库的表达不⼀致,
数据库中最终的执⾏sql为:SELECT ss.* FROM sim_signal_schedules ss WHERE ss.data_source = 2  AND ss.last_updated_date >= '10/25/2021 11:03:26.632'
and ss.schedule_id in ( 'b77b8df3-3272-4da3-9ff6-34fedc3ac823','bdf45c6e-47ed-44aa-b385-d5f04fe6cab0','d34878f9-fa12-4d17-bea1-45a37fc9eaa7');
问题出现了,数据库中date类型中的数据精确到了毫秒,但是binder输出的时候只是精确到秒,坑爹的是我当前的场景下数据还真就精确到了毫秒,这个不同框架下对于date类型的表达,让我了半天。。。
控制台输出jdbc的配置如下:
pml中引⼊依赖:
<dependency>
<groupId&lecode.log4jdbc</groupId>
<artifactId>log4jdbc</artifactId>
<version>1.2</version>
</dependency>
yml⽂件配置:
datasource: ##打印最终执⾏sql配置
isPrimary: 1
platform: postgres
url: jdbc:log4jdbc:postgresql://10.127.0.11:5432/ftc_simulation?stringtype=unspecified&useAffectedRows=true  //注意这⾥在jdbc和postgresql中添加了log4j
username: sim_dev
password: sim_dev
driver-class-name: net.sf.log4jdbc.DriverSpy  //driver-class-name有修改
type: com.zaxxer.hikari.HikariDataSource

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。