java收集sql监控_java笔记:自己动手写javaEE框架(三)--引入SQL监控技术P6spy

2023-12-29 04:30

本文主要是介绍java收集sql监控_java笔记:自己动手写javaEE框架(三)--引入SQL监控技术P6spy,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

软件151 黄旭 1531610120

任何系统里,日志和一定的监控是相当重要的,在一个软件整个生命周期里维护永远是大头同时是痛苦的,而日志和监控就是为后期维护提供了良好的基础和手段,在java工程里面大多使用log4j来记录系统日志,这个技术几乎所有的java工程师都很熟悉,不太明白了,大家可以查查百度。这里我打算引入一个能监控JDBC执行语句的框架到我写的java框架里面,这个框架非常的好用,他就是p6spy。

“如果优化SQL语句,如何进行系统调优”,这样的问题我想很多程序员都听到过,优化和调优是一个高难度的技术技能,只有具有扎实的技术功底和多年的项目经验才把他做好。我以前遇到这样的提问,思路很机械,都是从SQL语法,索引,分区,算法来考虑,其实优化和调优程序环境的搭配也是很重要的,例如,现在做java企业级项目,大多使用了orm技术,很少会直接去用jdbc操作数据库,而orm技术对jdbc的封装让最终执行的sql语句的原型离程序员越来越远,因此对jbdc执行的原生态的sql语句的掌控是相当重要的。

在这里我可以分享一下我的经验。我现在比较推崇ibatis,它既实现了orm思想,又保留了sql语句的使用而不是像hibernate那样对数据库做完全面向对象的映射,而产生了很多新的东西,比如hql。这是一个简便的设计,我觉得系统设计最佳的方案就是新老兼容。其实不同的程序员擅长的技术也不同,做java的程序员当然对java更熟悉,开发数据库的程序员对数据库很在行,假如你现在开发一个后台数据库数据量很大,业务操作很复杂的系统,我这里会首推ibatis技术做orm层,因为这样的大系统到了数据库层面和dba打交道很多,对sql语句以及数据库优化很多,而ibatis直接写sql语句的优点就很明显了,java程序员和dba的沟通和程序的交互也就方便多了。我最近做了几个这样的系统,系统做完后我都会把重要的sql语句从系统里抽取出来给dba优化,而dba优化后我基本只要拷贝到程序里就可以,为整个工作带来了便利。此外系统上线,如果操作数据库报错,在日志里提取sql语句,进行检查,检查后维护程序也是有很大的便利,最后用sql嵌入orm,程序架构的变迁所带来的问题也会少很多,因此我以后开发系统orm技术的首选就是ibatis了。

但是ibatis执行jdbc是使用prepareStatement,所以最终打印出来的sql语句是下面的格式:

48304ba5e6f9fe08f3fa1abda7d326ab.png

2011-10-13 11:17:36 Connection - {conn-100000} Connection

2011-10-13 11:17:36 Connection - {conn-100000} Preparing Statement: select t.username,t.password,t.enabled from users t where t.username = ?

2011-10-13 11:17:36 PreparedStatement - {pstm-100001} Executing Statement: select t.username,t.password,t.enabled from users t where t.username = ?

2011-10-13 11:17:36 PreparedStatement - {pstm-100001} Parameters: [sharpxiajun]

2011-10-13 11:17:36 PreparedStatement - {pstm-100001} Types: [java.lang.String]

48304ba5e6f9fe08f3fa1abda7d326ab.png

我们拷贝出sql语句还要改写,真是烦死人了,那么p6spy就能解决这个问题,它会把?替换成参数,看看我加入了p6spy后执行的效果吧。

|statement| select t.username,t.password,t.enabled from users t where t.username = 'sharpxiajun'

P6spy使用很简单,只要完成下面步骤就行:

1.将p6spy.jar包放到应用的classpath所在的路径中;

2.修改连接池或者连接配置的jdbc的驱动为p6spy所提供的保证后的驱动,com.p6spy.engine.spy.P6SpyDriver

3.修改spy.properties并将其放到类搜索目录.

下面我们开始开发了。

1.新的工程结构图如下:

1cd537ff973334959beca94b9fe985e4.png

新添两个jar包:log4j-1.2.12.jar和p6spy.jar

2.将log4j.properties和spy.properties拷贝到src下面(暂时拷贝到src下面,其实应该放到conf下面,因为现在都是在本地测试,没有发布到tomcat下面,就把两个文件拷贝到默认的路径下)

log4j.properties内容如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

log4j.debug=true

log4j.rootLogger=INFO,CONSOLE,STDOUT

#-----CONSOLE-----

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1} - %m%n

#-----SQL LOG-----

log4j.logger.java.sql.Connection=DEBUG

log4j.logger.java.sql.Statement=DEBUG

log4j.logger.java.sql.PreparedStatement=DEBUG

log4j.logger.com.ibatis=debug

log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug

log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug

log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug

48304ba5e6f9fe08f3fa1abda7d326ab.png

日志打印到控制台里,SQL LOG下的配置表示打印出jbdc以及ibatis的日志。

spy.properties内容如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

module.log=com.p6spy.engine.logging.P6LogFactory

realdriver=oracle.jdbc.driver.OracleDriver

deregisterdrivers=true

executionthreshold=

outagedetection=false

outagedetectioninterval=

filter=false

include =

exclude =

sqlexpression =

autoflush = true

dateformat=

includecategories=

excludecategories=info,debug,result,batch

stringmatcher=

stacktrace=false

stacktraceclass=

reloadproperties=false

reloadpropertiesinterval=60

useprefix=false

appender=com.p6spy.engine.logging.appender.StdoutLogger

append=true

log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender

log4j.appender.STDOUT.layout=org.apache.log4j.SimpleLayout

log4j.appender.STDOUT.layout.ConversionPattern=p6spy

log4j.logger.p6spy=DEBUG,STDOUT

48304ba5e6f9fe08f3fa1abda7d326ab.png

这里只要修改下realdriver=oracle.jdbc.driver.OracleDriver就行。

3.接下来我们只要更改下数据库的驱动就行了,修改下constants.properties,内容如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

#db.driverClass = oracle.jdbc.driver.OracleDriver

db.driverClass = com.p6spy.engine.spy.P6SpyDriver

db.user = sharpxiajun

db.password = sharpxiajun

db.jdbcUrl = jdbc:oracle:thin:@127.0.0.1:1521:orcl

#db.driverClass = com.mysql.jdbc.Driver

#db.user = root

#db.password = root

#db.jdbcUrl = jdbc\:mysql\://localhost\:3306/sq_xidi?useUnicode\=true&characterEncoding\=utf-8

48304ba5e6f9fe08f3fa1abda7d326ab.png

4.最后修改下USERS.xml配置文件,让查询方法接收到参数,如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

select t.username,t.password,t.enabled from users t

t.username = #username#

48304ba5e6f9fe08f3fa1abda7d326ab.png

执行结果如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

log4j: Parsing for [root] with value=[INFO,CONSOLE,STDOUT].

log4j: Level token is [INFO].

log4j: Category root set to INFO

log4j: Parsing appender named "CONSOLE".

log4j: Parsing layout options for "CONSOLE".

log4j: Setting property [conversionPattern] to [%d{yyyy-MM-dd HH:mm:ss} %c{1} - %m%n].

log4j: End of parsing for "CONSOLE".

log4j: Parsed "CONSOLE" options.

log4j: Parsing appender named "STDOUT".

log4j:ERROR Could not find value for key log4j.appender.STDOUT

log4j:ERROR Could not instantiate appender named "STDOUT".

log4j: Parsing for [com.ibatis.common.jdbc.SimpleDataSource] with value=[debug].

log4j: Level token is [debug].

log4j: Category com.ibatis.common.jdbc.SimpleDataSource set to DEBUG

log4j: Handling log4j.additivity.com.ibatis.common.jdbc.SimpleDataSource=[null]

log4j: Parsing for [java.sql.Connection] with value=[DEBUG].

log4j: Level token is [DEBUG].

log4j: Category java.sql.Connection set to DEBUG

log4j: Handling log4j.additivity.java.sql.Connection=[null]

log4j: Parsing for [com.ibatis] with value=[debug].

log4j: Level token is [debug].

log4j: Category com.ibatis set to DEBUG

log4j: Handling log4j.additivity.com.ibatis=[null]

log4j: Parsing for [java.sql.Statement] with value=[DEBUG].

log4j: Level token is [DEBUG].

log4j: Category java.sql.Statement set to DEBUG

log4j: Handling log4j.additivity.java.sql.Statement=[null]

log4j: Parsing for [com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate] with value=[debug].

log4j: Level token is [debug].

log4j: Category com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate set to DEBUG

log4j: Handling log4j.additivity.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=[null]

log4j: Parsing for [com.ibatis.common.jdbc.ScriptRunner] with value=[debug].

log4j: Level token is [debug].

log4j: Category com.ibatis.common.jdbc.ScriptRunner set to DEBUG

log4j: Handling log4j.additivity.com.ibatis.common.jdbc.ScriptRunner=[null]

log4j: Parsing for [java.sql.PreparedStatement] with value=[DEBUG].

log4j: Level token is [DEBUG].

log4j: Category java.sql.PreparedStatement set to DEBUG

log4j: Handling log4j.additivity.java.sql.PreparedStatement=[null]

log4j: Finished configuring.

初始化测试类....

2011-10-13 11:17:35 XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [conf/applicationContext.xml]

2011-10-13 11:17:35 GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext@2808b3: startup date [Thu Oct 13 11:17:35 CST 2011]; root of context hierarchy

2011-10-13 11:17:35 PropertyPlaceholderConfigurer - Loading properties file from class path resource [conf/constants.properties]

2011-10-13 11:17:35 DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1de17f4: defining beans [usersDao,userService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,propertyConfigurer,myDataSource,sqlMapClient,sqlMapClientTemplate,transactionManager,methodServiceAdvisor,org.springframework.aop.config.internalAutoProxyCreator,baseServiceMethods,org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0]; root of factory hierarchy

2011-10-13 11:17:35 MLog - MLog clients using log4j logging.

2011-10-13 11:17:35 C3P0Registry - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]

2011-10-13 11:17:36 AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 2wyjv28i1xq0ktewu9ral|131303f, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.p6spy.engine.spy.P6SpyDriver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 2wyjv28i1xq0ktewu9ral|131303f, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:oracle:thin:@127.0.0.1:1521:orcl, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]

2011-10-13 11:17:36 TransactionalTestExecutionListener - Began transaction (1): transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@6db33c]; rollback [false]

测试开始....

进入到了方法拦截器。。。。

调用的service:

cn.com.sharpxiajun.service.impl.UsersServiceImpl@23bdd1

调用的方法:

public abstract java.util.List cn.com.sharpxiajun.service.UsersService.queryUsersList(java.util.Map) throws java.lang.Exception

参数是:

{username=sharpxiajun}

2011-10-13 11:17:36 Connection - {conn-100000} Connection

2011-10-13 11:17:36 Connection - {conn-100000} Preparing Statement: select t.username,t.password,t.enabled from users t where t.username = ?

2011-10-13 11:17:36 PreparedStatement - {pstm-100001} Executing Statement: select t.username,t.password,t.enabled from users t where t.username = ?

2011-10-13 11:17:36 PreparedStatement - {pstm-100001} Parameters: [sharpxiajun]

2011-10-13 11:17:36 PreparedStatement - {pstm-100001} Types: [java.lang.String]

|statement| select t.username,t.password,t.enabled from users t where t.username = 'sharpxiajun'

返回结果是:

[]

拦截器执行结束!!

[]

测试结束!!

|commit|

2011-10-13 11:17:36 TransactionalTestExecutionListener - Committed transaction after test execution for test context [[TestContext@1fac852 testClass = UsersServiceImplTest, locations = array['classpath:conf/applicationContext.xml'], testInstance = cn.com.sharpxiajun.junittest.service.UsersServiceImplTest@1758cd1, testMethod = testQueryUserList@UsersServiceImplTest, testException = [null]]]

2011-10-13 11:17:36 GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@2808b3: startup date [Thu Oct 13 11:17:35 CST 2011]; root of context hierarchy

2011-10-13 11:17:36 DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1de17f4: defining beans [usersDao,userService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,propertyConfigurer,myDataSource,sqlMapClient,sqlMapClientTemplate,transactionManager,methodServiceAdvisor,org.springframework.aop.config.internalAutoProxyCreator,baseServiceMethods,org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0]; root of factory hierarchy

这篇关于java收集sql监控_java笔记:自己动手写javaEE框架(三)--引入SQL监控技术P6spy的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/548321

相关文章

springboot控制bean的创建顺序

《springboot控制bean的创建顺序》本文主要介绍了spring-boot控制bean的创建顺序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录1、order注解(不一定有效)2、dependsOn注解(有效)3、提前将bean注册为Bea

Java中的ConcurrentBitSet使用小结

《Java中的ConcurrentBitSet使用小结》本文主要介绍了Java中的ConcurrentBitSet使用小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、核心澄清:Java标准库无内置ConcurrentBitSet二、推荐方案:Eclipse

java中的Supplier接口解析

《java中的Supplier接口解析》Java8引入的Supplier接口是一个无参数函数式接口,通过get()方法延迟计算结果,它适用于按需生成场景,下面就来介绍一下如何使用,感兴趣的可以了解一下... 目录1. 接口定义与核心方法2. 典型使用场景场景1:延迟初始化(Lazy Initializati

Java中ScopeValue的使用小结

《Java中ScopeValue的使用小结》Java21引入的ScopedValue是一种作用域内共享不可变数据的预览API,本文就来详细介绍一下Java中ScopeValue的使用小结,感兴趣的可以... 目录一、Java ScopedValue(作用域值)详解1. 定义与背景2. 核心特性3. 使用方法

spring中Interceptor的使用小结

《spring中Interceptor的使用小结》SpringInterceptor是SpringMVC提供的一种机制,用于在请求处理的不同阶段插入自定义逻辑,通过实现HandlerIntercept... 目录一、Interceptor 的核心概念二、Interceptor 的创建与配置三、拦截器的执行顺

Java中Map的五种遍历方式实现与对比

《Java中Map的五种遍历方式实现与对比》其实Map遍历藏着多种玩法,有的优雅简洁,有的性能拉满,今天咱们盘一盘这些进阶偏基础的遍历方式,告别重复又臃肿的代码,感兴趣的小伙伴可以了解下... 目录一、先搞懂:Map遍历的核心目标二、几种遍历方式的对比1. 传统EntrySet遍历(最通用)2. Lambd

SQL Server 中的表进行行转列场景示例

《SQLServer中的表进行行转列场景示例》本文详细介绍了SQLServer行转列(Pivot)的三种常用写法,包括固定列名、条件聚合和动态列名,文章还提供了实际示例、动态列数处理、性能优化建议... 目录一、常见场景示例二、写法 1:PIVOT(固定列名)三、写法 2:条件聚合(CASE WHEN)四、

Spring Boot 中 RestTemplate 的核心用法指南

《SpringBoot中RestTemplate的核心用法指南》本文详细介绍了RestTemplate的使用,包括基础用法、进阶配置技巧、实战案例以及最佳实践建议,通过一个腾讯地图路线规划的案... 目录一、环境准备二、基础用法全解析1. GET 请求的三种姿势2. POST 请求深度实践三、进阶配置技巧1

springboot+redis实现订单过期(超时取消)功能的方法详解

《springboot+redis实现订单过期(超时取消)功能的方法详解》在SpringBoot中使用Redis实现订单过期(超时取消)功能,有多种成熟方案,本文为大家整理了几个详细方法,文中的示例代... 目录一、Redis键过期回调方案(推荐)1. 配置Redis监听器2. 监听键过期事件3. Redi

Spring Boot 处理带文件表单的方式汇总

《SpringBoot处理带文件表单的方式汇总》本文详细介绍了六种处理文件上传的方式,包括@RequestParam、@RequestPart、@ModelAttribute、@ModelAttr... 目录方式 1:@RequestParam接收文件后端代码前端代码特点方式 2:@RequestPart接