写点什么

Spring boot 记录 sql 探索,java 堆和栈面试题

用户头像
极客good
关注
发布于: 刚刚

原生 log+org.hibernate.EmptyInterceptor#


=====================================


org.hibernate.EmptyInterceptor 提供钩子,hibernate 本身提供 entity 的 curd 钩子。重写 EmptyInterceptor 方法,可以实现计数。但是 onPrepareStatement 方法只是装配 sql 前的事件,而且不是完整的 sql。


  • ?? 可以显示 sql

  • ? 不能和参数一行显示

  • ? 不能显示 limit 参数

  • ?? 能计数

  • ? 不能记录耗时


spring.jpa.properties.hibernate.ejb.interceptor=com.vison.itdoc.config.HibernateInterceptor


public class HibernateInterceptor extends EmptyInterceptor {


@Override


public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {


// Log.info("onload...", entity)


return true;


}


@Override


public String onPrepareStatement(String string) {


// count++


return INSTANCE.onPrepareStatement(string);


}


@Override


public void afterTransactionCompletion(Transaction t) {


INSTANCE.afterTransactionCompletion(t);


Log.info("after trans complete", t);


}


}


log4jdbc#


=========


log4jdbc 能很好的解决 sql 完整显示和记录耗时的问题


2021-02-23 19:59:13.709 INFO 97586 --- [nio-8081-exec-1] jdbc.sqltiming : select posts0_.id as id1_2_, posts0_.create_time as create_t2_2_, posts0_.modify_time as modify_t3_2_,


posts0_.content as content4_2_, posts0_.title as title5_2_ from posts posts0_ where 1=1 order


by posts0_.id asc limit 10 ;


{executed in 1 msec}


还能够定义超过 1 定时间的执行 sql 记录为 error 类型。


<dependency>


<groupId>com.googlecode.log4jdbc</groupId>


<artifactId>log4jdbc</artifactId>


<version>1.2</version>


<scope>runtime</scope>


</dependency>


spring.datasource.driver-class-name: net.sf.log4jdbc.DriverSpy


#使用 log4jdbc 后 mysql 的 url


spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/xxxx?useUnicode=true&characterEncoding=UTF-8


#使用 log4jdbc 后 oracle 的 url


#spring.datasource.url: jdbc:log4jdbc:oracle:thin:@127.0.0.1:1521:orcl


注意需要添加


spring.datasource.driver-class-name 和更改 spring.datasource.url 将 jdbc 改为 jdbc:log4jdbc


_log4jdbc.properties_可以定义更多配置


#配置为需要记录的包或类匹配路径


#log4jdbc.debug.stack.prefix=com.drp


#log4jdbc 加载的 drivers (驱动名)


#log4jdbc.drivers=oracle.jdbc.OracleDriver


log4jdbc.auto.load.popular.drivers=true


#在日志中显示 warn 警告


log4jdbc.statement.warn=true


#毫秒值.执行时间超过该值的 SQL 语句将被记录为 warn 级别.


log4jdbc.sqltiming.warn.threshold=2000


#毫秒值.执行时间超过该值的 SQL 语句将被记录为 error 级别.


log4jdbc.sqltiming.error.threshold=3000


#是把 boolean 记录为 'true'/'false' 还是 1/0. 默认设置为 false,不启用,为了移植性.


#log4jdbc.dump.booleanastruefalse=true


#输出的 sql,一行最大的字符数,默认 90. 以后新版可能为 0


#log4jdbc.dump.sql.maxlinelength=90


#如果在调试模式下转储,则转储整个堆栈跟踪 默认 false


log4jdbc.dump.fulldebugstacktrace=false


#是否记录某些类型的语句,默认 true


log4jdbc.dump.sql.select=true


log4jdbc.dump.sql.insert=true


log4jdbc.dump.sql.delete=true


log4jdbc.dump.sql.update=true


log4jdbc.dump.sql.create=true


#输出 sql 末尾处加入分号,默认 false


log4jdbc.dump.sql.addsemicolon=true


#将此设置为 false 以不修剪已记录的 SQL


log4jdbc.trim.sql=true


#将此设置为 false 不删除额外的空行


log4jdbc.trim.sql.extrablanklines=true


#log4jdbc.suppress.generated.keys.exception=false


  • ?? 可以显示 sql

  • ?? 不能和参数一起显示

  • ?? 不能显示 limit 参数

  • ? 能计数

  • ?? 能记录单个 sql 耗时

  • ? 不能统计总耗时


不足的是,单纯 log4jdbc 并不能满足所有。理论上 log4jdbc+


org.hibernate.EmptyInterceptor 可以满足需求了


P6Spy#


======


测试完毕,发现 P6Spy 目前最能满足需求:


  • ?? 可以显示 sql

  • ?? 不能和参数一起显示

  • ?? 不能显示 limit 参数

  • ?? 能计数

  • ?? 不能记录耗时

  • ?? 支持 curd 事件前后钩子,钩子参数返回 sql 和执行耗时及异常信息


<dependency>


<groupId>p6spy</groupId>


<artifactId>p6spy</artifactId>


<version>3.9.1</version>


</dependency>


同 log4jdbc 需要改 driver 和 url


spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver


spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/test?useLegacyDatetimeCode=false&serverTimezone=UTC


_psy.properties_可以定义更多配置


#modulelist=com.p6spy.engine.spy.P6SpyFactory,com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory


modulelist=com.vison.itdoc.config.CustomeP6Factory,com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFac


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


tory


#moduelist 很关键,我这里使用了自定义的 Factory,因为我需要自定义 event


appender=com.p6spy.engine.spy.appender.Slf4JLogger


logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat


customLogMessageFormat=%(executionTime) ms|%(category)|%(sql)


excludecategories=result,resultset,info,debug


正常使用默认配置就可以显示出 sql 和耗时信息


4 ms|statement|select admin0_.id as id1_0_, admin0_.create_time as create_t2_0_, admin0_.modify_time as modify_t3_0_, admin0_.email as email4_0_, admin0_.password as password5_0_, admin0_.status as status6_0_, admin0_.username as username7_0_ from admin admin0_ where admin0_.username='root'


可以看到,耗时信息和实际参数

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Spring boot记录sql探索,java堆和栈面试题