使用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

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

  1. jboss7 关闭日志打印_使用自定义日志记录处理程序在JBoss AS 7中跟踪SQL语句

    jboss7 关闭日志打印 使用ORM从您的特定数据库中提取数据并让其创建和发布您必须亲自编写的所有SQL语句似乎很方便. 这就是使ORM解决方案受欢迎的原因. 但是它也有一个缺点:由于ORM为您做了 ...

  2. 如何在ASP.NET Core中编写自定义日志记录提供程序

    目录 介绍 如何实现所需的接口 基础类和附件 FileLoggerProvider具体类及其附件 1. ConfigureLogging() 2. appsettings.json文件 介绍 源代码可 ...

  3. java emr_java – EMR – 在Hadoop(和YARN)中使用自定义日志记录appender

    在我们的EMR集群中,我们使用自定义log4j-appender和log4j.properties来允许我们将日志转发到Splunk并让我们做一些魔术,提供的库和配置不知道如何操作. 在EMR 3.x ...

  4. windows服务器系统的iis日志,Windows server2012 IIs 8 自定义日志记录

    问题: 通过CDN加速的网站,记录日志时无法追踪源IP,日志的IP都为CDN节点ip. 分析: 1.在解析记录header时,CDN实际会把源IP以其它header的形式回传,如网宿为[Cdn-Src ...

  5. ef mysql跟踪sql语句_EF Core 日志跟踪sql语句

    EF Core 日志跟踪sql语句 1.新增自定义ILoggerProvider实现类 public class EFLoggerProvider : ILoggerProvider { public ...

  6. 如何使用第三方日志记录提供程序替代.NET Core中的内置程序

    背景 .NET Core 支持适用于各种内置和第三方日志记录提供程序的日志记录 API. 先来看下如何将日志记录 API 与内置提供程序一起使用. 调用 CreateDefaultBuilder,这将 ...

  7. [pig4cloud框架源码分析] 03 - MyBatis中的sql语句日志打印

    文章目录 导读 pig4cloud框架配置 Mybatis Log Plugin 插件开启方式 插件说明 [TODO]源码分析 拦截器方案实现sql日志查看 参考资料 导读 使用MyBatis开发过程 ...

  8. 【2 - 数据库是如何存储数据的】Sql Server - 郝斌(字段、记录、表;图形化界面及sql语句建表;六种约束;一对一、一对多、多对多、数据库关系图;主外键)

    课程地址:数据库 SQLServer 视频教程全集(99P)| 22 小时从入门到精通_哔哩哔哩_bilibili 目录 数据库是如何解决数据存储问题的 1. 表的相关数据 2. create tab ...

  9. 关于借书卡Card,图书Book,借书记录 Borrow,三表根据题目要求写SQL语句。

    这三个表很综合的把SQL数据库查询语句给覆盖了,连接查询,模糊查询,编写触发器,视图等,有什么不会的可以评论交流,希望各位大牛多多指教. 借书卡:Card(Cno卡号,Name姓名,Class 班级) ...

最新文章

  1. Java 8 中 HashMap 到底有啥不同?
  2. vecm模型怎么写系数_第四十三讲 R-回归预测模型的自举重采样验证(boostrap-resampling)...
  3. 复杂数据权限设计方案
  4. nginx配置文件语法高亮的Sublime Text扩展
  5. (转)千万别熬夜:身体器官晚上工作时间表一览
  6. js负数比较大小_【建阳童小|阅享数学(第十一期)】负数的由来
  7. MSYS2+MinGW32 编译 QEMU需做的准备工作
  8. Linux automake命令
  9. 解决ubuntu下的firefox无法在线播放音频和视频的问题
  10. 深入理解CSS中的line-height的使用
  11. Android的线程使用来更新UI----Thread、Handler、Looper、Time...
  12. Android布局详解之一:FrameLayout
  13. 芯片制造工艺中的衡量指标
  14. 下载VS(visualstudio)2019官方网站详解
  15. imitate wechat - 0
  16. php 完成时钟,PHP 绘制时钟 高洛峰 细说PHP
  17. Win10桌面图标显示不正常变成了白色
  18. 极力推荐的微信小程序,超级实用,一定要收藏
  19. five86-2靶机渗透攻略
  20. 30天数据分析与机器学习实践之Day16——Python文本数据分析:新闻分类任务

热门文章

  1. 2017蓝桥杯省赛---java---B---8(包子凑数)
  2. mysql group和order_mysql 用 group by 和 order by同时使用
  3. github 公钥 私钥_github快速使用
  4. redis集群3种模式
  5. lambda表达式语法_使用类似Lambda的语法作为Java中的表达式进行切换
  6. corda_Corda服务的异步流调用
  7. 从事java编程技能要求_5道Java视频课程,提高您的编程技能
  8. spark在服务器运行示例_创建示例HTTPS服务器以获取乐趣和收益
  9. java使用泛型后消除泛型_如何以及何时使用泛型
  10. servlets_jQuery Ajax – Servlets集成:构建完整的应用程序