Mybaits 实现打印sql语句的代码

mybatis本身没有提供日志的实现,引入的是第三方组件。mybatis支持多个第三方日志插件,优先级由低到高为slf4J、commonsLoging、Log4J2、Log4J和JdkLog。

mybatis中有一个LogFactory,获取log的工厂类,在工程类中可以回去对应的日志实现。分析工程类,可以发现mybatis如何来选择log

public static Log getLog(String logger) {
 try {
 return logConstructor.newInstance(logger);
 } catch (Throwable t) {
 throw new LogException("Error creating logger for logger " + logger + ". Cause: " + t, t);
 }
}

关于logConstructor的加载如下

static {
 tryImplementation(LogFactory::useSlf4jLogging);
 tryImplementation(LogFactory::useCommonsLogging);
 tryImplementation(LogFactory::useLog4J2Logging);
 tryImplementation(LogFactory::useLog4JLogging);
 tryImplementation(LogFactory::useJdkLogging);
 tryImplementation(LogFactory::useNoLogging);
}
private static void tryImplementation(Runnable runnable) {
 if (logConstructor == null) {
 try {
  runnable.run();
 } catch (Throwable t) {
  // ignore
 }
 }
}

在 tryImplementation ,中会设置mybatis使用的log类型。把引用的log设置到logConstructor中后,后续其他类型的log也不会再加载。所以在mybatis中优先级由低到高为slf4J、commonsLoging、Log4J2、Log4J和JdkLog。感觉也是属于SPI的一种实现方式,不同的是各种类型的第三方日志,无法形成一个统一的接口。故此,mybatis为了解决这一问题,使用了适配器模式。

适配器的实现一般是让适配器实现或者继承目标,并且内部持有一个适配者的引用。这样调用目标对象方法,实际上是调用适配者的方法。

mybatis 又是如何把这log,用起来的。根据mybatis的习惯,应该会使用代理模式,来打印这个日志。 举例查询的语句查看,根据MapperProxy,查到最后查询的语句

public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
 Statement stmt = null;
 try {
 Configuration configuration = ms.getConfiguration();
 StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
 stmt = prepareStatement(handler, ms.getStatementLog());
 return handler.query(stmt, resultHandler);
 } finally {
 closeStatement(stmt);
 }
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
 Statement stmt;
 Connection connection = getConnection(statementLog);
 stmt = handler.prepare(connection, transaction.getTimeout());
 handler.parameterize(stmt);
 return stmt;
}
protected Connection getConnection(Log statementLog) throws SQLException {
 Connection connection = transaction.getConnection();
 if (statementLog.isDebugEnabled()) {
 return ConnectionLogger.newInstance(connection, statementLog, queryStack);
 } else {
 return connection;
 }
}

到此处可以看到mybatis在获取连接的时候,会根据日志的打印级别来判断是否会创建一个代理类。到这里就基本可以猜到,在代理类中,mybatis会去打印这个sql的语句

public static Connection newInstance(Connection conn, Log statementLog, int queryStack) {
 InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack);
 ClassLoader cl = Connection.class.getClassLoader();
 return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
}

用 ConnectionLogger 来举例,看到里面的invoke的方法

public Object invoke(Object proxy, Method method, Object[] params)
 throws Throwable {
 try {
 if (Object.class.equals(method.getDeclaringClass())) {
  return method.invoke(this, params);
 }
 if ("prepareStatement".equals(method.getName())) {
  if (isDebugEnabled()) {
  debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
  }
  PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
  stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
  return stmt;
 } else if ("prepareCall".equals(method.getName())) {
  if (isDebugEnabled()) {
  debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
  }
  PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
  stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
  return stmt;
 } else if ("createStatement".equals(method.getName())) {
  Statement stmt = (Statement) method.invoke(connection, params);
  stmt = StatementLogger.newInstance(stmt, statementLog, queryStack);
  return stmt;
 } else {
  return method.invoke(connection, params);
 }
 } catch (Throwable t) {
 throw ExceptionUtil.unwrapThrowable(t);
 }
}

可以看到,mybatis在里面还可以更具情况创建代理类。代理类又一次被代理,这也是mybatis喜欢的编程方式,比如插件也是代理类再次被代理,来实现多个插件并行。

到此这篇关于Mybaits 实现打印sql语句的代码的文章就介绍到这了,更多相关Mybaits 打印sql语句内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mybaits非配置原因,导致SqlSession was not registered for synchronization异常

    今天运行程序时报了 SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@69d4fb43] was not registered for synchronization because synchronization is not active [11:03:17]-Closing non transactional SqlSession [org.apache.ibatis.session.defaults.Defa

  • Mybaits配置文件之动态SQL配置备忘录

    动态参数拼接的查询语句 –传入参数类型为自定义数据类型 <select id="queryMessageList" parameterType="com.imooc.bean.Message" resultMap="MessageResult"> select ID,COMMAND,DESCRIPTION,CONTENT from MESSAGE where 1=1 <if test="command !=null &

  • Mybaits 实现打印sql语句的代码

    mybatis本身没有提供日志的实现,引入的是第三方组件.mybatis支持多个第三方日志插件,优先级由低到高为slf4J.commonsLoging.Log4J2.Log4J和JdkLog. mybatis中有一个LogFactory,获取log的工厂类,在工程类中可以回去对应的日志实现.分析工程类,可以发现mybatis如何来选择log public static Log getLog(String logger) { try { return logConstructor.newInsta

  • Mybatis 实现打印sql语句的代码

    mybatis本身没有提供日志的实现,引入的是第三方组件.mybatis支持多个第三方日志插件,优先级由低到高为slf4J.commonsLoging.Log4J2.Log4J和JdkLog. mybatis中有一个LogFactory,获取log的工厂类,在工程类中可以回去对应的日志实现.分析工程类,可以发现mybatis如何来选择log public static Log getLog(String logger) { try { return logConstructor.newInsta

  • Mybatis控制台打印Sql语句的实现代码

    MyBatis简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 下面看下Mybatis控制台打印Sql语句 1.首先将ibatis log4j运行级别调到DEBUG可以在控制台打印出ibatis运行的sql语

  • 调试Django时打印SQL语句的日志代码实例

    这篇文章主要介绍了调试Django时打印SQL语句的日志代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 设置里面添加如下代码: LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': {

  • cakephp打印sql语句的方法

    本文实例讲述了cakephp打印sql语句的方法.分享给大家供大家参考.具体实现方法如下: 将以下语句复制到你的代码中,可以打印出在这之前所有的sql语句: $sources = ConnectionManager::sourceList(); if (!isset($logs)): $logs = array(); foreach ($sources as $source): $db =& ConnectionManager::getDataSource($source); if (!$db-

  • springboot+mybatis-plus 两种方式打印sql语句的方法

    1.注解方式,yml文件配置上以下就可以直接使用 mybatis-plus: mapper-locations: classpath:mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 2.这一种网上没有,搜过好多资料都没有,我是配置多数据源,所以是在代码中写的config那么yml文件就是失效的,只能一个一个配置,到了打印sql的时候,就怎么都是找不到,后来设置的源码找到灵感,发现可

  • springmvc+mybatis 做分页sql 语句实例代码

    废话不多说了,直接给大家贴代码了,具体代码如下所示: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="s

  • Mybatis控制台打印SQL语句的两种方式实现

    问题描述 在使用mybatis进行开发的时候,由于可以动态拼接sql,这样大大方便了我们.但是也有一定的问题,当我们动态sql拼接的块很多的时候,我们要想从*mapper.xml中直接找出完整的sql就会非常的难,这个时候经常会需要把组合之后的完整sql调试出来比较好.下面来看两种调试出sql的两种方式 解决方案 方案1: 网上说的比较多的,之前也是这么用的一种方式 1:首先将ibatis log4j运行级别调到DEBUG可以在控制台打印出ibatis运行的sql语句 2:添加如下语句: ###

  • 使用BAT批处理执行sql语句的代码

    1.把待执行Sql保存在一个文件,这里为20110224.sql.2.新建一个扩展名.bat的批处理文件,输入下面命令并保存后,双击.bat文件,系统会自动执行20110224.sql的语句: 复制代码 代码如下: osql -S gdjlc -d TestDB -U sa -P 1 -i 20110224.sql osql参数见下面=======================================================================: E:\>osql

  • php与mysql建立连接并执行SQL语句的代码

    今天写了一个小程序,很小很小,只不过是能够建立php与mysql的链接,并且实现简单的SQL语句. 新手初试,还请各路高手多多指导. 程序源代码如下: 复制代码 代码如下: <?php $conn = mysql_connect("localhost","root","") or die ("wrong!"); $sel=mysql_select_db("mydb",$conn); $sql=&quo

随机推荐