Mybatis 실행쿼리 interceptor에 적용하기

2025. 1. 29. 00:43Java/mybatis

package com.hys.home.interceptor;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@Slf4j
@Intercepts({
    @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class SqlLogInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // Get the StatementHandler
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();

        // Get the BoundSql
        BoundSql boundSql = statementHandler.getBoundSql();

        // Get the raw SQL and parameters
        String rawSql = boundSql.getSql();
        Object parameterObject = boundSql.getParameterObject();

        // Replace '?' placeholders with actual parameter values
        String finalSql = replacePlaceholdersWithValues(rawSql, boundSql, parameterObject);

        // Log the final SQL
        log.info("Executing SQL:\n{}", finalSql);

        // Proceed with the original method
        return invocation.proceed();
    }

    private String replacePlaceholdersWithValues(String rawSql, BoundSql boundSql, Object parameterObject) {
        // Get the parameter mappings from the BoundSql
        List<org.apache.ibatis.mapping.ParameterMapping> parameterMappings = boundSql.getParameterMappings();

        if (parameterMappings == null || parameterMappings.isEmpty()) {
            return rawSql; // If there are no parameters, return the raw SQL
        }

        // If the parameterObject is a Map, cast it for easier value retrieval
        Map<String, Object> paramMap = (parameterObject instanceof Map) ? (Map<String, Object>) parameterObject : null;

        // Replace '?' placeholders with actual parameter values
        for (org.apache.ibatis.mapping.ParameterMapping parameterMapping : parameterMappings) {
            String propertyName = parameterMapping.getProperty(); // Get the parameter name

            // Get the value from the parameter object
            Object value = (paramMap != null) ? paramMap.get(propertyName) : getValueFromObject(parameterObject, propertyName);

            // Format the value for SQL (e.g., wrap strings in quotes, handle nulls)
            String valueAsString = (value == null) ? "null" : "'" + value.toString() + "'";
            rawSql = rawSql.replaceFirst("\\?", valueAsString.replace("$", "\\$")); // Avoid regex issues with "$"
        }

        return rawSql;
    }

    private Object getValueFromObject(Object parameterObject, String propertyName) {
        try {
            // Use reflection or commons-beanutils to get the value of the property
            return org.apache.commons.beanutils.BeanUtils.getProperty(parameterObject, propertyName);
        } catch (Exception e) {
            // If the property doesn't exist, return null
            return null;
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // No additional properties needed
    }
}

'Java > mybatis' 카테고리의 다른 글

Mybatis 로그에 실행 쿼리 출력하기  (0) 2025.01.29
Mybatis 로그에 쿼리 찍히게 하기  (0) 2025.01.28
Mybatis where절 if문으로 처리  (0) 2025.01.19
Mybatis 쿼리 결과 출력하기  (0) 2025.01.18
Mybatis 반복문 처리  (0) 2025.01.15