[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[整理]Mybatis拦截器,记录所有sql异常

上一篇:[备忘]net.sf.ehcache.util.UpdateChecker - Update check failed: java.net.SocketTimeoutException: connec
下一篇:[备忘]HttpConnection的超时时间设置不上的问题~

添加日期:2016/6/15 17:11:25 快速返回   返回列表 阅读8951次
(1)spring的配置文件里,


<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
     <property name="dataSource" ref="dataSource" />
    <!-- 分页插件设置 -->
    <property name="plugins">
       <array>
         <!-- SQL异常拦截器 -->
         <bean class="com.xxx.yyyy.interceptor.SqlExceptionInterceptor"></bean>
       </array>
    </property>
</bean>  



(2)SqlExceptionInterceptor.java的内容:


package com.xxx.yyyy.interceptor;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
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;
import org.apache.ibatis.session.RowBounds;

import com.xxx.domain.SqlExceptionLog;
import com.xxx.persistence.SqlExceptionLogMapper;
import com.xxx.utils.SpringContextHolder;

/**
 * Mybatis拦截器. 拦截SQL执行时的异常,写入DB.
 * 
 */
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {
                MappedStatement.class, Object.class }),
        @Signature(type = Executor.class, method = "query", args = {
                MappedStatement.class, Object.class, RowBounds.class,
                ResultHandler.class }) })
public class SqlExceptionInterceptor implements Interceptor {

    /**
     * 线程池.
     */
    private static ExecutorService executor = Executors.newFixedThreadPool(5);

    /**
     * 拦截方法.
     */
    public Object intercept(Invocation invocation) throws Throwable {

        try {
            return invocation.proceed();
        } catch (Exception e) {

            try {
                // 取得各种值
                MappedStatement statement = (MappedStatement) invocation
                        .getArgs()[0];
                Object parameter = invocation.getArgs()[1];
                BoundSql boundSql = statement.getBoundSql(parameter);

                // 防止死循环
                if (statement.getId().toUpperCase()
                        .contains("sqlExceptionLogMapper".toUpperCase())) {
                    throw e;
                }

                // 日志对象
                final SqlExceptionLog record = new SqlExceptionLog();
                record.setSystemName("ordersystem"); // 系统名称
                record.setSqlId(statement.getId()); // sqlId
                record.setSqlParameter(parameter.toString()); // SQL参数
                record.setSqlSource(boundSql.getSql()); // SQL语句
                record.setSqlType(statement.getSqlCommandType().toString()); // SQL类型
                record.setExceptionMessage(e.getCause().toString()); // 异常简要信息
                record.setExceptionStack(getExceptionStackTrace(e)); // 堆栈信息
                record.setCreateTime(new Date()); // 创建时间

                // 放入线程池
                executor.execute(new Runnable() {
                    public void run() {

                        // 外面类里直接注入貌似有问题,故这么搞下。
                        SqlExceptionLogMapper mapper = SpringContextHolder
                                .getBean("sqlExceptionLogMapper");
                        mapper.insertSelective(record);
                    }
                });
            } catch (Exception ex) {
                ex.printStackTrace();
            }

            // 抛出异常
            throw e;
        }
    }

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

    /**
     * 配置文件读取属性.
     */
    public void setProperties(Properties properties) {
    }

    /**
     * 获取异常的堆栈信息.
     * 
     * @param e
     * @return
     */
    private String getExceptionStackTrace(Exception e) {
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        e.printStackTrace(new java.io.PrintWriter(buf, true));
        String expMessage = buf.toString();
        try {
            buf.close();
        } catch (IOException ex) {
        }
        return expMessage;
    }
}



(3)SqlExceptionLog表的结构如下:


CREATE TABLE `sql_exception_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `systemName` varchar(30) NOT NULL COMMENT '系统名称',
  `sqlId` varchar(200) NOT NULL COMMENT 'sql所在类、方法名',
  `sqlSource` varchar(2000) NOT NULL COMMENT 'sql内容',
  `sqlParameter` varchar(500) DEFAULT NULL COMMENT 'sql参数',
  `sqlType` varchar(10) DEFAULT NULL COMMENT 'sql类型,SELECT、INSERT等',
  `exceptionMessage` varchar(500) DEFAULT NULL COMMENT '异常信息',
  `exceptionStack` mediumtext COMMENT '异常堆栈信息',
  `createTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='sql异常日志';


自己生成bean和Mapper即可。

(4)SpringContextHolder.java的内容:


package com.shijie99.order.common.utils;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextHolder implements ApplicationContextAware {

    /**
     * 以静态变量保存ApplicationContext,可在任意代码中取出ApplicaitonContext.
     */
    private static ApplicationContext context;

    /**
     * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
     */
    public void setApplicationContext(ApplicationContext context) {
        SpringContextHolder.context = context;
    }

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    /**
     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        return (T) context.getBean(name);
    }
}

 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved