Mybatis打印sql(不使用xml)

  • 前言

   博主在刚开始做开发的,对于mybatis如何打印sql完全不理解,看到网上全是通过xml来配置打印sql,因为之前博主全是使用javaConfig配置mybatis信息,所以觉得为了打印sql加单独加一个配置文件十分的麻烦,网上大部分又是千篇一律的推荐使用xml,所以博主就在官网找不依赖配置文件打印sql的方法,现在分享给大家。

 

  • 正文

我们直接看mybatis官网:

可以看到,mybatis第一个推荐使用的就是xml,但是这显然不是博主想要的答案,所以,继续往下看:

 可以看到,mybatis提供了不使用配置文件的方法打印sql,接下来我们就来看看,怎么在不使用xml的前提下打印sql。

方法一:

使用官网推荐的org.apache.ibatis.logging.LogFactory.useLog4JLogging(),在spring容器初始化之前,调用这个方法,让mybatis使用log4j打印sql:

import org.apache.ibatis.logging.log4j.Log4jImpl;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

@Configuration
@ComponentScan("com.cht")
@MapperScan("com.cht.dao")
public class AppConfig {

    @PostConstruct
    public void init(){
        org.apache.ibatis.logging.LogFactory.useLog4JLogging();
    }

   @Bean
    public DataSource dataSource(){
       DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
       driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
       driverManagerDataSource.setUsername("tzgdev");
       driverManagerDataSource.setPassword("123456");
       driverManagerDataSource.setUrl("jdbc:mysql://192.168.4.12:3306/tzgdev?useUnicode=true&characterEncoding=UTF-8");
       return driverManagerDataSource;
   }

    @Bean
   public SqlSessionFactoryBean sqlSessionFactoryBean(){
       SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
       /*org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
       configuration.setLogImpl(Log4jImpl.class);*/
       sqlSessionFactoryBean.setDataSource(dataSource());
       return sqlSessionFactoryBean;
   }
}

为什么调用这个方法就可以打印sql了呢?我们来看下源码,我们打开org.apache.ibatis.logging.LogFactory,可以看到这个类当中有一段静态代码块:

static {
        tryImplementation(new Runnable() {
            public void run() {
                LogFactory.useSlf4jLogging();
            }
        });
        tryImplementation(new Runnable() {
            public void run() {
                LogFactory.useCommonsLogging();
            }
        });
        tryImplementation(new Runnable() {
            public void run() {
                LogFactory.useLog4J2Logging();
            }
        });
        tryImplementation(new Runnable() {
            public void run() {
                LogFactory.useLog4JLogging();
            }
        });
        tryImplementation(new Runnable() {
            public void run() {
                LogFactory.useJdkLogging();
            }
        });
        tryImplementation(new Runnable() {
            public void run() {
                LogFactory.useNoLogging();
            }
        });
    }

在当中run了6个方法,我们来看第一个run()方法:

    private static void setImplementation(Class<? extends Log> implClass) {
        try {
            Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
            Log log = (Log)candidate.newInstance(LogFactory.class.getName());
            if (log.isDebugEnabled()) {
                log.debug("Logging initialized using '" + implClass + "' adapter.");
            }

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

 

可以看到,mybatis通过不同的类,去反射得到不同的日志对象,再来看tryImplementation()这个方法:

    private static void tryImplementation(Runnable runnable) {
        if (logConstructor == null) {
            try {
                runnable.run();
            } catch (Throwable var2) {
            }
        }

    }

可以看到当实例化出来一个日志对象之后,就不会调用run()方法了,看到这里,大家肯定觉得奇怪,如果是这样,那之前加了log4j依赖不就可以直接打印sql了吗?这其实这是mybatis整合spring5的一个坑,spring5使用的是spring-jcl,所以会跑第二个run()方法,但是jcl默认是使用jul的,并且不支持log4j只支持log4j2(不懂的童鞋可以去看博主上一篇文章--spring5日志新特性详解),那为什么用jul无法打印sql呢?看源码可以知道,jcl底层的日志级别是FINE,而我们在log.properties中用的是DEBUG级别,所以当整合spring跟myBatis的时候,只引入log4j包的话是不能打印sql的。

 方法二:

在实例化sqlSessionFactory的时候,调用LogFactory的useCustomLogging()方法,跟xml的使用注解的方式一样:

import org.apache.ibatis.logging.log4j.Log4jImpl;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;


@Configuration
@ComponentScan("com.cht")
@MapperScan("com.cht.dao")
public class AppConfig {

    /*@PostConstruct
    public void init(){
        org.apache.ibatis.logging.LogFactory.useLog4JLogging();
    }*/

   @Bean
    public DataSource dataSource(){
       DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
       driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
       driverManagerDataSource.setUsername("tzgdev");
       driverManagerDataSource.setPassword("123456");
       driverManagerDataSource.setUrl("jdbc:mysql://192.168.4.12:3306/tzgdev?useUnicode=true&amp;characterEncoding=UTF-8");
       return driverManagerDataSource;
   }

    @Bean
   public SqlSessionFactoryBean sqlSessionFactoryBean(){
       SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
       org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
       configuration.setLogImpl(Log4jImpl.class);
       sqlSessionFactoryBean.setDataSource(dataSource());
       return sqlSessionFactoryBean;
   }
}

可以看到博主在实例化sqlSessionFactory的时候,调用了这段代码:

org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
       configuration.setLogImpl(Log4jImpl.class);

那么这个方法是干嘛的呢?我们来看源码:

    public void setLogImpl(Class<? extends Log> logImpl) {
        if (logImpl != null) {
            this.logImpl = logImpl;
            LogFactory.useCustomLogging(this.logImpl);
        }

    }
public static synchronized void useCustomLogging(Class<? extends Log> clazz) {
        setImplementation(clazz);
    }

可以看到博主通过这个方法传了log4j类进去,给logConstructor赋了log4j的构造方法,这样logConstructor不为空,所以也不会去创建其他日志对象,当然直接调用LogFactory.useCustomLogging(Log4jImpl.class)或org.apache.ibatis.logging.LogFactory.useLog4JLogging()也一样:

 

    综上就是博主自己研究的mybatis不依靠xml实现打印sql日志的方法,希望对大家有所帮助。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值