How to configure Log4j in Spring for MyBatis SQL queries?

Lucky picture Lucky · Mar 22, 2016 · Viewed 7.9k times · Source

I have the a Spring MVC project with mybatis 3.3.0 and mybatis-spring 1.2.3 and I want to configure log4j in my project. And I'm not using mybatis-config.xml for setting up mybatis sql session factory. So I cannot use the following setting,

<configuration>
  <settings>
    ...
    <setting name="logImpl" value="LOG4J"/>
    ...
  </settings>
</configuration>

So, I have the following config in my

spring-context.xml,

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="typeAliasesPackage" value="com.sample.model"/>
  <property name="mapperLocations" value="classpath*:com/sample/mappers/*.xml" />
</bean>

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg index="0" ref="sqlSessionFactory" />
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="com.sample.mappers" />
</bean>

And configured this log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>

  <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d [%p] %c{1} - %m%n"/>
    </layout>
  </appender>

  <logger name="java.sql" additivity="false">
    <level value="debug"/>
   <appender-ref ref="STDOUT"/> 
  </logger>

  <logger name="org.apache.ibatis" additivity="false">
    <level value="debug"/>
    <appender-ref ref="STDOUT"/>
  </logger>

  <logger name="org.mybatis.spring" additivity="false">
    <level value="debug"/>
    <appender-ref ref="STDOUT"/>
  </logger>

  <logger name="com.sample.mappers">
    <level value="debug"/>
    <appender-ref ref="STDOUT"/>
  </logger>

  <root>
    <priority value ="debug" />
    <appender-ref ref="STDOUT" />
  </root>

</log4j:configuration>

The above configuration doesn't print the sql queries executed or the prepared statements. So as documented in mybatis logging page and from this answer, I used the log4j.properties instead of xml config,

log4j.properties

# Global logging configuration
log4j.rootLogger=DEBUG, stdout

# MyBatis logging configuration...
log4j.logger.com.sample.mappers=DEBUG

# SqlMap logging configuration.
log4j.logger.org.mybatis.spring=DEBUG
log4j.logger.org.apache.ibatis=DEBUG
log4j.logger.org.apache.ibatis.jdbc.ScriptRunner=DEBUG

log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG

# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%p] %c{1} - %m%n

I had the common-logging removed from the pom.xml too. But that also doesn't seem to work.

  • How to set MyBatis to print all the sql queries(PreparedStatements)?
  • If in case MyBatis is not detecting the log4j, Is there any way to tell MyBatis to use log4j as the default logging framework without using the mybatis-config.xml?

Answer

Lucky picture Lucky · Mar 22, 2016

I found the solution and now I can see all the Prepared Statements and all of the Mapper interface queries & parameters in my console. Invoking this line of code once the server started up before calling any MyBatis queries works fine,

org.apache.ibatis.logging.LogFactory.useLog4JLogging();

Other methods for other loggin frameworks are mentioned here.

If you choose to call one of these methods, you should do so before calling any other MyBatis method. Also, these methods will only switch to the requested log implementation if that implementation is available on the runtime classpath. For example, if you try to select Log4J logging and Log4J is not available at runtime, then MyBatis will ignore the request to use Log4J and will use it's normal algorithm for discovering logging implementations.

I also hided the following two dependencies in my pom.xml,

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.6.1</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.1</version>
</dependency>

Once I set to use log4j as default logger using useLog4JLogging() method, in console I could see MyBatis picking up the log4j as its logger framework now.

[DEBUG] org.apache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.