Mybatis拦截器实现记录历史数据到MongoDB

背景需求

项目中使用的持久层框架Mybatis,我们使用MongoDB记录所有的更新历史记录,方便项目出问题时便于分析。将所有的数据的更新,即新增修改删除的记录,都记录在MongoDB中,可以通过RockMongo这个工具查找。

实现

自己写了一个拦截器,用于拦截Executor执行器的Update方法。通过解析参数,在目标方法即Update方法执行前后对数据进行处理,最终将数据记录到MongoDB中。

package com.sk.sams.common.mybatis.changemonitor;

import java.util.List;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
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 com.sk.sams.common.mybatis.changemonitor.domain.ChangeData;
import com.sk.sams.common.mybatis.changemonitor.listener.ChangeEventListener;
import com.sk.sams.common.mybatis.changemonitor.mybatis.MybatisInvocation;
import com.sk.sams.common.mybatis.changemonitor.parse.DataPaser;
import com.sk.sams.common.mybatis.changemonitor.parse.ParseFactory;

/**
 * 拦截器,拦截Executor的Update方法,即数据库的更新操作,Insert,Update,Delete都会拦截
 * @author sailing.yang
 *
 */
@Intercepts(value = {
		@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class ChangeMinitorInterceptor implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		// 拦截目标
		Object target = invocation.getTarget();

		Object result = null;
		if (target instanceof Executor) {
			Object[] args = invocation.getArgs();
			MappedStatement ms = (MappedStatement) args[0];
			Object parameter = args[1];
			String commandName = ms.getSqlCommandType().name();

			ChangeEventListener changeEventListener = ChangeEventListener.getInstance();

			DataPaser dataPaser = ParseFactory.getInstance().creator(commandName);
			MybatisInvocation mybatisInvocation = new MybatisInvocation(args, ms, parameter, (Executor) target);
			// 方法执行之前解析数据
			List<ChangeData> changeTable = dataPaser.parseBefore(commandName, mybatisInvocation);

			// 执行Update方法,除了查询之外的Insert,Delete,Update都是属于Update方法
			result = invocation.proceed();

			// 方法执行之后处理数据
			changeTable = dataPaser.parseAfter(mybatisInvocation, changeTable);

			if (changeTable != null) {
				changeEventListener.listenModification(commandName, changeTable);
			}
		}
		return result;
	}

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

	@Override
	public void setProperties(Properties arg0) {

	}

}

这个拦截器需要配置在mybatis的配置文件中:

<plugins>
		<!-- com.github.pagehelper为PageHelper类所在包名 -->
		<plugin interceptor="com.github.pagehelper.PageHelper">
			<!-- 该参数默认为false -->
			<!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 -->
			<!-- 和startPage中的pageNum效果一样 -->
			<property name="offsetAsPageNum" value="true" />
			<!-- 该参数默认为false -->
			<!-- 设置为true时,使用RowBounds分页会进行count查询 -->
			<property name="rowBoundsWithCount" value="true" />
			<!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 -->
			<!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型) -->
			<property name="pageSizeZero" value="true" />
			<!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 -->
			<!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
			<!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
			<property name="reasonable" value="false" />
			<!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 -->
			<!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 -->
			<!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值 -->
			<!-- 不理解该含义的前提下,不要随便复制该配置 -->
			<property name="params" value="pageNum=start;pageSize=limit;" />
		</plugin>
		
		<plugin interceptor="com.sk.sams.common.mybatis.changemonitor.ChangeMinitorInterceptor" />
	</plugins>

MongoDB效果

如果想要源码,请去这里下载,需要5积分哟。

https://download.csdn.net/download/susu0510/10606209

猜你喜欢

转载自blog.csdn.net/susu0510/article/details/81706248