1. 程式人生 > >Mybtis與Spring結合使用Log4J列印日誌/Sql到控制檯

Mybtis與Spring結合使用Log4J列印日誌/Sql到控制檯

首先說明一下,專案採用SpringMVC+Mybatis的架構,日誌工具還是最常用的log4j2,整合框架之後發現無法列印SQL語句,只有報錯時才會列印。

然後開始看Mybatis的官方文件,關於日誌這一塊是怎麼處理的,下面是官方文件關於日誌的說明:

Logging

Mybatis內建的日誌工廠提供日誌功能,具體的日誌實現有以下幾種工具:

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j
  • JDK logging

具體選擇哪個日誌實現工具由MyBatis的內建日誌工廠確定。它會使用最先找到的(按上文列舉的順序查詢)如果一個都未找到,日誌功能就會被禁用。

不少應用伺服器的classpath中已經包含Commons Logging,如Tomcat和WebShpere, 所以MyBatis會把它作為具體的日誌實現。記住這點非常重要。這將意味著,在諸如 WebSphere的環境中——WebSphere提供了Commons Logging的私有實現,你的Log4J配置將被忽略。 這種做法不免讓人悲催,MyBatis怎麼能忽略你的配置呢?事實上,因Commons Logging已經存在了,按照優先順序順序,Log4J自然就被忽略了!不過,如果你的應用部署在一個包含Commons Logging的環境, 而你又想用其他的日誌框架,你可以通過在MyBatis的配置檔案mybatis-config.xml裡面新增一項setting(配置)來選擇一個不同的日誌實現。

<configuration><settings>
    ...
    <settingname="logImpl"value="LOG4J"/>
    ...
  </settings></configuration>

logImpl可選的值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING 或者是實現了介面org.apache.ibatis.logging.Log的類的完全限定類名, 並且這個類的建構函式需要是以一個字串(String型別)為引數的。 (可以參考org.apache.ibatis.logging.slf4j.Slf4jImpl.java的實現)

你根據需要呼叫如下的某一方法:

org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging();
org.apache.ibatis.logging.LogFactory.useStdOutLogging();

如果的確需要呼叫以上的某個方法,請在其他所有MyBatis方法之前呼叫它。另外,只有在相應日誌實現中存在 的前提下,呼叫對應的方法才是有意義的,否則MyBatis一概忽略。如你環境中並不存在Log4J,你卻呼叫了 相應的方法,MyBatis就會忽略這一呼叫,代之預設的查詢順序查詢日誌實現。

關於SLF4J、Apache Commons Logging、Apache Log4J和JDK Logging的API介紹已經超出本文件的範圍。 不過,下面的例子可以作為一個快速入門。關於這些日誌框架的更多資訊,可以參考以下連結:

Logging Configuration


MyBatis可以對包、類、名稱空間和全限定的語句記錄日誌。

具體怎麼做,視使用的日誌框架而定,這裡以Log4J為例。配置日誌功能非常簡單:新增幾個配置檔案, 如log4j.properties,再添加個jar包,如log4j.jar。下面是具體的例子,共兩個步驟:

步驟1: 新增 Log4J 的 jar 包

因為採用Log4J,要確保在應用中對應的jar包是可用的。要滿足這一點,只要將jar包新增到應用的classpath中即可。 Log4J的jar包可以從上面的連結中下載。

具體而言,對於web或企業應用,需要將log4j.jar 新增到WEB-INF/lib 目錄; 對於獨立應用, 可以將它新增到jvm的-classpath啟動引數中。

步驟2:配置Log4J

配置Log4J比較簡單, 比如需要記錄這個mapper介面的日誌:

package org.mybatis.example;publicinterfaceBlogMapper{@Select("SELECT * FROM blog WHERE id = #{id}")Blog selectBlog(int id);}

只要在應用的classpath中建立一個名稱為log4j.properties的檔案, 檔案的具體內容如下:

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p[%t]-%m%n

新增以上配置後,Log4J就會把 org.mybatis.example.BlogMapper 的詳細執行日誌記錄下來,對於應用中的其它類則僅僅記錄錯誤資訊。

也可以將日誌從整個mapper介面級別調整到到語句級別,從而實現更細粒度的控制。如下配置只記錄 selectBlog 語句的日誌:

log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE

與此相對,可以對一組mapper介面記錄日誌,只要對mapper介面所在的包開啟日誌功能即可:

log4j.logger.org.mybatis.example=TRACE

某些查詢可能會返回大量的資料,只想記錄其執行的SQL語句該怎麼辦?為此,Mybatis中SQL語 句的日誌級別被設為DEBUG(JDK Logging中為FINE),結果日誌的級別為TRACE(JDK Logging中為FINER)。所以,只要將日誌級別調整為DEBUG即可達到目的:

log4j.logger.org.mybatis.example=DEBUG

要記錄日誌的是類似下面的mapper檔案而不是mapper介面又該怎麼呢?

<?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"><mappernamespace="org.mybatis.example.BlogMapper"><selectid="selectBlog"resultType="Blog">
    select * from Blog where id = #{id}
  </select></mapper>

對這個檔案記錄日誌,只要對名稱空間增加日誌記錄功能即可:

log4j.logger.org.mybatis.example.BlogMapper=TRACE

進一步,要記錄具體語句的日誌可以這樣做:

log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE

看到了吧,兩種配置沒差別!

配置檔案log4j.properties的餘下內容是針對日誌格式的,這一內容已經超出本 文件範圍。關於Log4J的更多內容,可以參考Log4J的網站。不過,可以簡單試一下看看,不同的配置 會產生什麼不一樣的效果。

附:監控其他sql語句輸出的log4j配置如下:

#-----------------------------------#
# alibaba druid
log4j.logger.druid.sql=INFO
log4j.logger.druid.sql.DataSource=info
log4j.logger.druid.sql.Connection=info
log4j.logger.druid.sql.Statement=info
log4j.logger.druid.sql.ResultSet=info

# mybatis 顯示SQL語句部分
log4j.logger.org.mybatis=DEBUG

# jdbc sql

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