[Spring] Mybatis의 QueryLog를 변수명으로 찍기

half·2023년 9월 25일
0

개발을 하다보면 쿼리로그를 ? 나 실제 변수에 들어간 값이 아닌 값이 담겨져 있는 변수로 찍어야 하는 경우가 발생한다.

Mybatis Interceptor를 통해 쿼리를 찍을 수 있다.

1) MybatisInterceptor 클래스 추가

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;

@Intercepts({
	@Signature(type=StatementHandler.class, method="update", args={Statement.class}),
	@Signature(type=StatementHandler.class, method="query", args={Statement.class, ResultHandler.class})
})
public class MybatisInterceptor implements Interceptor {
	
    private static final Logger logger = LoggerFactory.getLogger(MybatisInterceptor.class);
    
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StatementHandler handler = (StatementHandler)invocation.getTarget();
		
		BoundSql boundSql = handler.getBoundSql();
		
		String sql = boundSql.getSql();
		
		Object param = handler.getParameterHandler().getParameterObject();
		
		if(param == null) {
			sql = sql.replaceFirst("\\?", ":");
		} else {
			if(param instanceof Integer || param instanceof Long || param instanceof Float || param instanceof Double) {
				sql = sql.replaceFirst("\\?", param.toString());
			} else if(param instanceof String) {
				sql = sql.replaceFirst("\\?", "'" + param + "'");
			} else if(param instanceof Map) {
				
				List<ParameterMapping> paramMapping = boundSql.getParameterMappings();
				for(ParameterMapping mapping : paramMapping) {
					String propValue = mapping.getProperty();
					sql = sql.replaceFirst("\\?", ":" + propValue);
				}
			} else {
				List<ParameterMapping> paramMapping = boundSql.getParameterMappings();
				for(ParameterMapping mapping : paramMapping) {
					String propValue = mapping.getProperty();
					sql = sql.replaceFirst("\\?", ":" + propValue);

				}
			}
			
		}
	if(log.isDebugEnabled()) {	
		log.debug("SQL QUERY :: \n{}", sql);
	}	
	return invocation.proceed();
	}
	
	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}
	
	@Override
	public void setProperties(Properties properties) {
		// null
	}
}

interceptor를 통해 실제 값이 들어가는 부분을 변수로 대체해 쿼리를 찍고 로그레벨이 debug 가 아닐 경우엔 로직을 타지 않도록 설정할 수 있다.

2) SqlSessionFactory에 설정

SqlSessionFactory Bean을 생성할 때 plugin 설정에 추가해줄 수 있다.

SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setPlugins(new MybatisInterceptor());
profile
아메리카노 수혈 받는 중

0개의 댓글