Mybatis 쿼리 로그 출력

쿼리 검수를 위해 mybatis 플러그인에 아래 interceptor를 추가

 - 바인딩 변수에 값이 맵핑되어 있는 쿼리문 출력가능


@Intercepts({ @Signature(type = StatementHandler.class, method = "update", args = { Statement.class }),
@Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class }) })
public class MybatisSqlLogInterceptor implements Interceptor {
private static Logger sqlLog = LoggerFactory.getLogger("MYBATIS_SQL_LOG");
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler handler = (StatementHandler) invocation.getTarget();
String sql = bindSql(handler); // SQL 추출
sqlLog.info("=====================================================================");
sqlLog.info("{} ", sql);
sqlLog.info("=====================================================================");
return invocation.proceed();
}
/**
* <pre>
* bindSql
*
* <pre>
*
* @param boundSql
* @param sql
* @param param
* @return
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
@SuppressWarnings("rawtypes")
private String bindSql(StatementHandler handler) throws NoSuchFieldException, IllegalAccessException {
BoundSql boundSql = handler.getBoundSql();
// 쿼리실행시 맵핑되는 파라미터를 구한다
Object param = handler.getParameterHandler().getParameterObject();
// 쿼리문을 가져온다(이 상태에서의 쿼리는 값이 들어갈 부분에 ?가 있다)
String sql = boundSql.getSql();
// 바인딩 파라미터가 없으면
if (param == null) {
sql = sql.replaceFirst("\\?", "''");
return sql;
}
// 해당 파라미터의 클래스가 Integer, Long, Float, Double 클래스일 경우
if (param instanceof Integer || param instanceof Long || param instanceof Float || param instanceof Double) {
sql = sql.replaceFirst("\\?", param.toString());
}
// 해당 파라미터의 클래스가 String인 경우
else if (param instanceof String) {
sql = sql.replaceFirst("\\?", "'" + param + "'");
}
// 해당 파라미터의 클래스가 Map인 경우
else if (param instanceof Map) {
List<ParameterMapping> paramMapping = boundSql.getParameterMappings();
for (ParameterMapping mapping : paramMapping) {
String propValue = mapping.getProperty();
Object value = ((Map) param).get(propValue);
if (value == null) {
continue;
}
if (value instanceof String) {
sql = sql.replaceFirst("\\?", "'" + value + "'");
} else {
sql = sql.replaceFirst("\\?", value.toString());
}
}
}
// 해당 파라미터의 클래스가 사용자 정의 클래스인 경우
else {
List<ParameterMapping> paramMapping = boundSql.getParameterMappings();
Class<? extends Object> paramClass = param.getClass();
for (ParameterMapping mapping : paramMapping) {
String propValue = mapping.getProperty();
Field field = paramClass.getDeclaredField(propValue);
field.setAccessible(true);
Class<?> javaType = mapping.getJavaType();
if (String.class == javaType) {
sql = sql.replaceFirst("\\?", "'" + field.get(param) + "'");
} else {
sql = sql.replaceFirst("\\?", field.get(param).toString());
}
}
}
// return sql
return sql;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}




[SQL Map Config]

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

        <settings>

               <setting name="cacheEnabled" value="false" />

               <setting name="useGeneratedKeys" value="true" />

               <setting name="defaultExecutorType" value="REUSE" />

        </settings>

       

        <plugins>

            <plugin interceptor="com.test.common.mybatis.MybatisSqlLogInterceptor"/>

        </plugins>

       

</configuration>



[Logback Config]

<appender name="MYBATIS_SQL_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">

        <File>/home/test/${SERVER_NAME}/tomcat/logs/sql/mybatis_sql.log</File>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

            <fileNamePattern>/home/test/${SERVER_NAME}/tomcat/logs/sql/mybatis_sql.%d{yyyy-MM-dd}.log.gz</fileNamePattern>

            <maxHistory>60</maxHistory>

        </rollingPolicy>

        <encoder>

            <Pattern>%m%n</Pattern>

        </encoder>

    </appender>

 

 

<logger name="MYBATIS_SQL_LOG" level="info" additivity="false">

               <appender-ref ref="MYBATIS_SQL_LOG_FILE" />

        </logger>