mybaits小插件【sql拦截器】

写了一个sql拦截器用于打印sql语句的日志

package com.logext.sql.mybatis;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
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.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

/**
 * <p> Title: SqlLogInterceptor </p>
 * <p> Description: 日志中记录完整sql语句,及 更新类sql语句执行后影响行数的 拦截器</p>
 * <p> Copyright: CMBC Copyright (c) 2013 </p>
 * <p> Company: CMBC </p>
 * 
 * @author chenlong
 * 
 * @version
 * @since 1.0
 */
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
                RowBounds.class, ResultHandler.class }),
        @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class })
})
public class SqlLogInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        
        // 记录完整sql语句日志
        logCompleteSql(invocation);
        
        // 返回到mybatis执行路径
        Object ret = invocation.proceed();
        
        // 记录更新类sql语句执行后影响行数日志
        logEffectedRows(ret, invocation);
        
        return ret;
    }
    
    /**
     * 记录完整sql语句日志
     * @param invocation
     * @throws Throwable
     */
    public void logCompleteSql(Invocation invocation) throws Throwable {

        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object parameterObject = args[1];

        Log statementLog = mappedStatement.getStatementLog();
        if(!statementLog.isDebugEnabled()){
            
            return;
        }
        
        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);

        Configuration configuration = mappedStatement.getConfiguration();
        
        String originalSql = boundSql.getSql();
        
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        if(parameterMappings == null || parameterMappings.size()==0){
            
            statementLog.debug("==> Complete SQL: " + originalSql);
            
            return;
        }

        StringBuffer buf = new StringBuffer();
        
        MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
        
        StringTokenizer sqlTokenizer = new StringTokenizer(originalSql, "?");
        int tokenIndex = 0;
        while (sqlTokenizer.hasMoreTokens()) {

            buf.append(sqlTokenizer.nextToken());
            
            Object value = null;
            
            if(tokenIndex < parameterMappings.size()){
                ParameterMapping parameterMapping = parameterMappings.get(tokenIndex);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    
                    String propertyName = parameterMapping.getProperty();
                    if (boundSql.hasAdditionalParameter(propertyName)) {
                        value = boundSql.getAdditionalParameter(propertyName);
                    }
                    else if (parameterObject == null) {
                        value = null;
                    }
                    else {
                        value = metaObject == null ? null : metaObject.getValue(propertyName);
                    }
                    
                }
            }
            
            if(value != null){
                appendParameter(value, buf);
            }
            else if(sqlTokenizer.hasMoreTokens()){
                append("NULL", buf);
            }
            
            tokenIndex++;
        }
                
        statementLog.debug("==> Complete SQL: " + buf.toString());
    }

    /**
     * 记录更新类sql语句执行后影响行数日志
     * @param retObj
     * @param statementLog
     * @param methodName
     */
    public void logEffectedRows(Object retObj, Invocation invocation){
        
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        
        Log statementLog = mappedStatement.getStatementLog();
        if(!statementLog.isDebugEnabled()){
            
            return;
        }
        
        if(retObj!=null && (retObj instanceof Integer) && "update".equals(invocation.getMethod().getName())){
            
            statementLog.debug("==> Effected rows: " + retObj);
        }
    }
    
    public void appendParameter(Object param, Appendable appender) {
        if (param == null) {
            append("NULL", appender);
            return;
        }

        if (param instanceof Number //
            || param instanceof Boolean) {
            append(param.toString(), appender);
            return;
        }

        if (param instanceof String) {
            String text = (String) param;
            if ((text == null) || (text.length() == 0)) {
                append("NULL", appender);
            } else {
                append("'", appender);
                append(text.replaceAll("'", "''"), appender);
                append("'", appender);
            }
            return;
        }

        if (param instanceof Date) {
            append((Date) param, appender);
            return;
        }

        if (param instanceof InputStream) {
            append("'<InputStream>", appender);
            return;
        }

        if (param instanceof Reader) {
            append("'<Reader>", appender);
            return;
        }

        if (param instanceof Blob) {
            append("'<Blob>", appender);
            return;
        }

        if (param instanceof NClob) {
            append("'<NClob>", appender);
            return;
        }

        if (param instanceof Clob) {
            append("'<Clob>", appender);
            return;
        }

        append("'" + param.getClass().getName() + "'", appender);
    }
    
    public void append(char value, Appendable appender) {
        try {
            appender.append(value);
        } catch (IOException e) {
            throw new RuntimeException("println error", e);
        }
    }

    public void append(int value, Appendable appender) {
        append(Integer.toString(value), appender);
    }

    public void append(Date date, Appendable appender) {
        SimpleDateFormat dateFormat;
        if (date instanceof java.sql.Timestamp) {
            dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        } else {
            dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        }
        append("'" + dateFormat.format(date) + "'", appender);
    }

    public void append(long value, Appendable appender) {
        append(Long.toString(value), appender);
    }

    public void append(String text, Appendable appender) {
        try {
            appender.append(text);
        } catch (IOException e) {
            throw new RuntimeException("println error", e);
        }
    }
    
    @Override
    public Object plugin(Object target) {

        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

        // Do nothing
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值