我用过两次,

1.一次是数据库以前数据可以为null,现在不想为null,然后不想改代码,所以在插入或修改数据的时候,查一次,把为null的数据变一下,字符串变“”,数字变0或-1

下面的就是设置监听

<plugins>
		<!-- com.github.pagehelper为PageHelper类所在包名 -->
		<plugin interceptor="com.github.pagehelper.PageHelper">
			<!-- 4.0.0以后版本可以不设置该参数 -->
			<property name="dialect" value="mysql"/>
			<!-- 该参数默认为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.banksteel.erp.pfpurchase.util.EntityInterceptor"></plugin>
	</plugins>

  方法EntityInterceptor.java

package com.banksteel.erp.pfpurchase.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

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

/**
 * 
 * @description: 防止插入出现null
 * @projectName:finance-inventorybook-service
 * @author: 
 * @createTime:2017年11月30日 上午9:37:30
 */
@Intercepts(value =
{ @Signature(type = Executor.class, method = "update", args =
{ MappedStatement.class, Object.class }) })
public class EntityInterceptor implements Interceptor
{

	@Override
	public Object intercept(Invocation invocation) throws Throwable
	{
		final Object[] args = invocation.getArgs();
		MappedStatement ms = (MappedStatement) args[0];
		Object obj = args[1];

		// 插入时初始化为null的字段
		if (SqlCommandType.INSERT == ms.getSqlCommandType())
		{
			if (obj instanceof List<?>)
			{
				List<?> list = (List<?>) obj;
				for (Object item : list)
				{
					null2default(item);
				}
			} else
			{
				null2default(obj);
			}
		}

		return invocation.proceed();
	}

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

	@Override
	public void setProperties(Properties properties)
	{

	}

	/**
	 * 
	 * @description: 将实体类的属性由null设置为默认值,这里没有变数字的,只变了字符串
	 * @param obj
	 * @author:
	 * @createTime:2017年11月2日 下午5:19:56
	 */
	public static <T> void null2default(T obj)
	{
		if (null == obj)
		{
			return;
		}

        Method[] methods=obj.getClass().getMethods();
        Map<String,Method> setMethodMap = new HashMap<>();
        for (Method method : methods){
            if(method.getName().startsWith("set")){
                setMethodMap.put(method.getName(),method);
            }
        }

        for (Method method : methods){
            if((method.getName().length() < 3) || (!method.getName().startsWith("get"))){
                //只调用get函数
                continue;
            }
            //排除带有参数列表的方法
            Class<?>[] pts =method.getParameterTypes();
            if(null != pts && 0 < pts.length){
                continue;
            }
            //排除值不为null的get方法
            try {
                if(null != method.invoke(obj)){
                    continue;
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

            //找出get方法对应的set方法
            char[] cs = method.getName().toCharArray();
            cs[0] = 's';
            Method setMethod = setMethodMap.get(String.valueOf(cs));
            if(null == setMethod){
                continue;
            }

            //设置默认值
            Class<?> retClazz = method.getReturnType();
            try {
                if(Objects.equals(retClazz,String.class)){
                    setMethod.invoke(obj, "");
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        setMethodMap.clear();
	}

//    public static void main(String args[]){
//        ResourceAuditInfo ra = new ResourceAuditInfo();
//        null2default(ra);
//        System.out.println(JSONObject.toJSONString(ra));
//    }
}

  2.如果不是用上面的分页,就用另一种监听

<!-- 创建SqlSessionFactory,同时指定数据源 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<!--<property name="mapperLocations" value="classpath*:com/banksteel/openerp/system/provider/DAOImpl/*Mapper.xml" 
			/> -->
		<property name="mapperLocations" value="classpath*:mybatis/mapper/*Mapper.xml" />
		<!-- MyBatis拦截器,拦截SQL语句处理companyId -->
		<property name="plugins">
			<array>
				<bean
					class="com.banksteel.openerp.commons.interceptor.RebuildSqlInterceptor" />
			</array>
		</property>
	</bean>

  Rexxx.java,这里可以查找到要修改的sql或查询的条件,再这里都可以修改

package com.banksteel.openerp.commons.interceptor;

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

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
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.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.banksteel.openerp.commons.filter.SaasParameter;
import com.banksteel.openerp.commons.utils.RebuildSqlUtils;

import cn.mysteel.util.StringUtils;

/**
 * 重建SQL语句拦截器
 * 
 * @author KangJian
 *
 */
// MyBatis中Statement语句是通过RoutingStatementHandler对象的 prepare方法生成的,注解声明拦截此方法
@Intercepts({ @Signature(method = "prepare", type = StatementHandler.class, args = { Connection.class }) })
public class RebuildSqlInterceptor implements Interceptor {

	static Logger logger = LoggerFactory.getLogger(RebuildSqlInterceptor.class);

	public Object intercept(Invocation invocation) throws Throwable {

		// long start = System.currentTimeMillis();

		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
		// 创建反射工具类,用于获取和设置SQL语句
		MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);

		// 获取拦截的SQL语句
		MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
		BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");

		// 获取本地线程变量
		Long memberId = 0L;
		try {
			if (StringUtils.isNotEmpty(SaasParameter.getMemberId())) {
				memberId = Long.parseLong(SaasParameter.getMemberId());
			}
		} catch (Exception e) {
			logger.error("【noSaas拦截构建】会员ID转换异常,id=" + memberId, e);
		}

		if (!mappedStatement.getId().endsWith("noSaas")) {
			// 当statement的id不以noSaas结尾,且memberId>0,则执行对INSERT与SELECT语句的重构
			if ("SELECT".equals(mappedStatement.getSqlCommandType().toString()) && memberId > 0) {
				List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
				metaStatementHandler.setValue("delegate.boundSql.sql", RebuildSqlUtils.rebuildQuery(boundSql.getSql(),
						SaasParameter.getMemberId(), parameterMappings));
			} else if ("INSERT".equals(mappedStatement.getSqlCommandType().toString()) && memberId > 0) {
				metaStatementHandler.setValue("delegate.boundSql.sql",
						RebuildSqlUtils.rebuildInsert(boundSql.getSql(), SaasParameter.getMemberId()));
			}
		} else {
			// 当statement的id以noSaas结尾,为语句添加memberId额外参数
			if ("SELECT".equals(mappedStatement.getSqlCommandType().toString())
					|| "INSERT".equals(mappedStatement.getSqlCommandType().toString())) {
				boundSql.setAdditionalParameter("memberId", memberId);
				metaStatementHandler.setValue("delegate.boundSql", boundSql);
			}
		}
		Object result = invocation.proceed();
		// System.out.println("拦截耗时:" + (System.currentTimeMillis() - start));
		return result;
	}

	public Object plugin(Object target) {
		// 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数
		if (target instanceof StatementHandler) {
			return Plugin.wrap(target, this);
		} else {
			return target;
		}
	}

	public void setProperties(Properties properties) {

	}

}

  

转载于:https://www.cnblogs.com/guilf/p/9287893.html

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐