在系统开发过程中,涉及到数据库操作都是SQL的天下,基于ORM的各类框架来简化开发;在JPA/Hibernate方案中,只提供了SQL的打印输出,但并未输入SQL的参数值是多少,这里将解决这个问题,告知具体如何来实现这个操作。
1. 技术栈的介绍
JDK 1.8, Spring Boot 2.0.3.RELEASE, Mysql 5.7
2. 依赖包
Spring Boot中的JPA依赖包:
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
mysql
mysql-connector-java
com.googlecode.log4jdbc
log4jdbc
1.2
3. log4jdbc的介绍
log4jdbc使用SLF4J(Simple Logging Facade For Java)作为日志系统。特性:
综合一句话,log4jdbc可以帮我们实现一个抓取SQL中实际使用值的功能。
4. Spring Boot示例
application.properties内容:
spring.datasource.driver-class-name = net.sf.log4jdbc.DriverSpy
spring.datasource.url= jdbc:log4jdbc:mysql://127.0.0.1:3306/demo?useUnicode=yes&characterEncoding=UTF-8&useSSL=false
spring.datasource.username = root
spring.datasource.password = 123123
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.initialization-mode=never
spring.datasource.hikari.minimum-idle=0
spring.datasource.hikari.idle-timeout=10800000
spring.datasource.hikari.max-lifetime=21600000
spring.datasource.hikari.connection-timeout=6000
spring.datasource.hikari.initialization-fail-timeout=0
spring.datasource.hikari.data-source-properties.useUnicode=true
spring.datasource.hikari.data-source-properties.characterEncoding=utf8
spring.datasource.hikari.data-source-properties.useSSL=false
spring.datasource.hikari.data-source-properties.cachePrepStmts=true
spring.datasource.hikari.data-source-properties.prepStmtCacheSize=512
spring.datasource.hikari.data-source-properties.allowMultiQueries=true
spring.datasource.hikari.data-source-properties.useLocalSessionState=true
spring.datasource.hikari.data-source-properties.prepStmtCacheSqlLimit=81920
spring.datasource.hikari.data-source-properties.rewriteBatchedStatements=false
spring.datasource.hikari.data-source-properties.useOldAliasMetadataBehavior=true
spring.datasource.hikari.data-source-properties.createDatabaseIfNotExist=true
spring.jpa.open-in-view=false
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.hbm2ddl.import_files=data.sql
spring.jpa.show-sql=true
这里需要注意的是mysql的原来的驱动程序.driver-class-name 和mysql的url
spring.datasource.driver-class-name = net.sf.log4jdbc.DriverSpy
spring.datasource.url= jdbc:log4jdbc:mysql://127.0.0.1:3306/demo?useUnicode=yes&characterEncoding=UTF-8&useSSL=false
将被 net.sf.log4jdbc.DriverSpy来替代,可以理解为DriverSpy做为mysql驱动的代理来捕捉SQL的信息。
数据库连接的URL需要进行修改为:
原来的: jdbc:mysql://localhost:3306/mealsystem
现在的: jdbc:log4jdbc:mysql://localhost:3306/mealsystem
除此之外,无需额外的变化需求,其余代码都一致即可获得运行中的SQL信息。
2018-09-04 11:18:52.429 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.isValid(5) returned true
2018-09-04 11:18:52.429 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.getAutoCommit() returned true
2018-09-04 11:18:52.429 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.setAutoCommit(false) returned
Hibernate: select userpo0_.id as id1_0_0_, userpo0_.address as address2_0_0_, userpo0_.books as books3_0_0_, userpo0_.name as name4_0_0_, userpo0_.phone as phone5_0_0_ from user userpo0_ where userpo0_.id=?
2018-09-04 11:18:52.468 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.new PreparedStatement returned
2018-09-04 11:18:52.468 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.prepareStatement(select userpo0_.id as id1_0_0_, userpo0_.address as address2_0_0_, userpo0_.books as books3_0_0_, userpo0_.name as name4_0_0_, userpo0_.phone as phone5_0_0_ from user userpo0_ where userpo0_.id=?) returned net.sf.log4jdbc.PreparedStatementSpy@810bf7d
2018-09-04 11:18:52.475 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.setInt(1, 1) returned
2018-09-04 11:18:52.477 INFO 10184 --- [nio-8081-exec-2] jdbc.sqlonly : select userpo0_.id as id1_0_0_, userpo0_.address as address2_0_0_, userpo0_.books as books3_0_0_,
userpo0_.name as name4_0_0_, userpo0_.phone as phone5_0_0_ from user userpo0_ where userpo0_.id=1
2018-09-04 11:18:52.478 INFO 10184 --- [nio-8081-exec-2] jdbc.sqltiming : select userpo0_.id as id1_0_0_, userpo0_.address as address2_0_0_, userpo0_.books as books3_0_0_,
userpo0_.name as name4_0_0_, userpo0_.phone as phone5_0_0_ from user userpo0_ where userpo0_.id=1
{executed in 1 msec}
2018-09-04 11:18:52.481 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.new ResultSet returned
2018-09-04 11:18:52.481 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.executeQuery() returned net.sf.log4jdbc.ResultSetSpy@2bb7b913
2018-09-04 11:18:52.489 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.next() returned true
2018-09-04 11:18:52.498 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.getString(address2_0_0_) returned bj0
2018-09-04 11:18:52.498 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.wasNull() returned false
2018-09-04 11:18:52.498 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.getString(books3_0_0_) returned [{"name": "c++", "price": 53.9}, {"name": "java", "price": 100}]
2018-09-04 11:18:52.498 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.wasNull() returned false
2018-09-04 11:18:52.538 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.getString(name4_0_0_) returned xiaoming
2018-09-04 11:18:52.538 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.wasNull() returned false
2018-09-04 11:18:52.538 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.getString(phone5_0_0_) returned ["15510062270", "15516676760"]
2018-09-04 11:18:52.538 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.wasNull() returned false
2018-09-04 11:18:52.543 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.next() returned false
2018-09-04 11:18:52.575 INFO 10184 --- [nio-8081-exec-2] jdbc.resultset : 2. ResultSet.close() returned
2018-09-04 11:18:52.576 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.getMaxRows() returned 0
2018-09-04 11:18:52.576 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.getQueryTimeout() returned 0
2018-09-04 11:18:52.576 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.close() returned
Hibernate: update user set address=?, books=?, name=?, phone=? where id=?
2018-09-04 11:18:52.596 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.new PreparedStatement returned
2018-09-04 11:18:52.596 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.prepareStatement(update user set address=?, books=?, name=?, phone=? where id=?) returned net.sf.log4jdbc.PreparedStatementSpy@741f652
2018-09-04 11:18:52.596 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.setString(1, "bj0") returned
2018-09-04 11:18:52.597 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.setString(2, "[{"name":"c++","price":53.9},{"name":"java","price":100.0}]") returned
2018-09-04 11:18:52.597 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.setString(3, "xiaoming") returned
2018-09-04 11:18:52.597 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.setString(4, "["15510062270","15516676760"]") returned
2018-09-04 11:18:52.597 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.setInt(5, 1) returned
2018-09-04 11:18:52.597 INFO 10184 --- [nio-8081-exec-2] jdbc.sqlonly : update user set address='bj0', books='[{"name":"c++","price":53.9},{"name":"java","price":100.0}]',
name='xiaoming', phone='["15510062270","15516676760"]' where id=1
2018-09-04 11:18:52.598 INFO 10184 --- [nio-8081-exec-2] jdbc.sqltiming : update user set address='bj0', books='[{"name":"c++","price":53.9},{"name":"java","price":100.0}]',
name='xiaoming', phone='["15510062270","15516676760"]' where id=1
{executed in 1 msec}
2018-09-04 11:18:52.598 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.executeUpdate() returned 1
2018-09-04 11:18:52.598 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.getMaxRows() returned 0
2018-09-04 11:18:52.598 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.getQueryTimeout() returned 0
2018-09-04 11:18:52.598 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. PreparedStatement.close() returned
2018-09-04 11:18:52.605 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.commit() returned
2018-09-04 11:18:52.605 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.setAutoCommit(true) returned
2018-09-04 11:18:52.607 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.clearWarnings() returned
2018-09-04 11:18:52.607 INFO 10184 --- [nio-8081-exec-2] jdbc.audit : 2. Connection.clearWarnings() returned
可以发现其select和update语句是有具体的值存在的,额外还有执行所使用的时间。
2018-09-04 11:18:52.478 INFO 10184 --- [nio-8081-exec-2] jdbc.sqltiming : select userpo0_.id as id1_0_0_, userpo0_.address as address2_0_0_, userpo0_.books as books3_0_0_,
userpo0_.name as name4_0_0_, userpo0_.phone as phone5_0_0_ from user userpo0_ where userpo0_.id=1
{executed in 1 msec}
2018-09-04 11:18:52.598 INFO 10184 --- [nio-8081-exec-2] jdbc.sqltiming : update user set address='bj0', books='[{"name":"c++","price":53.9},{"name":"java","price":100.0}]',
name='xiaoming', phone='["15510062270","15516676760"]' where id=1
{executed in 1 msec}
6. 参考资料