Mybatis随笔-生活工作点滴

Mybatis自定义拦截器,处理通用接口

2019-07-11  本文已影响17人  东方不喵

在日常开发业务场景中,经常要遇到对 实体进行通用性操作,如:

  1. 进行持久化时,出现的保存 创建人信息
  2. 更新数据时候,通用更新 操作人信息
  3. 指定接口自定义主键,等
    为了解决这类问题,可以采用AOP 也可以采用拦截器,以下是采用MyBatis拦截器进行实现的
设置通用实体参数
@Data
public class BaseEntity {

    @TableId
    private String id;

    private Date createTime;

    /**
     *  删除状态:
     *  1 : 已删除
     *  0 :未删除
     */
    @Column(nullable = false)
    private Integer isDeleted;
}

@Data
@MappedSuperclass
public class CommonBaseEntity extends BaseEntity implements CreatorSetterImpl, UpdaterSetterImpl {

    /**
     *  创建人ID
     */
    private String creatorId;

    /**
     *  创建人姓名
     */
    private String creatorName;

    /**
     *  最后更新人ID
     */
    private String updaterId;

    /**
     *  最后更新人姓名
     */
    private String updaterName;

    /**
     *  最后更新时间
     */
    private Date updateTime;

}

创建用户接口 CreatorSetterImpl
public interface CreatorSetterImpl {

    void setCreatorId(String creatorId);

    void setCreatorName(String creatorName);

}
更新用户接口 UpdaterSetterImpl
public interface UpdaterSetterImpl {

    void setUpdaterId(String updaterId);

    void setUpdaterName(String updaterName);

    void setUpdateTime(Date updateTime);
}

编写拦截器


/**
 * @ClassName: BaseEntityMapperInterceptor
 * @Author: ren
 * @Description:
 * @CreateTIme: 2019/7/8 0008 下午 5:26
 **/
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class BaseEntityMapperInterceptor implements Interceptor, WapperInterface {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        //获取代理对象,由于注解的反射,返回的为   确定类型 StatementHandler 的实例对象
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();

        //通过包装类,把statementHandler包装成一个可以调用反射的代理对象
        MetaObject metaObject = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY);

        //事实上拦截到的时RoutingStatementHandler,需要调用其中的 delegate 属性,才可以调用到  mappedStatement,然后通过反射调用获取到mappedStatement对象
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");

        DefaultParameterHandler parameterHandler = (DefaultParameterHandler) metaObject.getValue("delegate.parameterHandler");

        //获取查询映射的名称
        String id = mappedStatement.getId();
        String methodName = id.substring(id.lastIndexOf(".") + 1);

        Log4jUtils.getInstance(getClass()).debug("进行通用拦截:" + methodName);
        Object parameter = parameterHandler.getParameterObject();

        if (methodName.matches("save.*")) {
            // 配置通用变量
            initSaveMethod(parameter);
            if (parameter instanceof HashMap) {

                HashMap map = (HashMap) parameter;

                map.forEach((k, v) -> {
                    if (v instanceof Collection) {
                        Collection collection = (Collection) v;

                        collection.forEach(obj -> {
                            // 配置通用变量
                            initSaveMethod(obj);
                        });
                    }
                });

            }
        } else if (methodName.matches("update.*")) {

            initUpdateMethod(parameter);
            if (parameter instanceof HashMap) {
                HashMap map = (HashMap) parameter;

                map.forEach((k, v) -> {
                    if (v instanceof Collection) {
                        Collection collection = (Collection) v;

                        collection.forEach(obj -> {
                            // 配置通用变量
                            initUpdateMethod(obj);
                        });
                    }
                });
            }


        }

        return invocation.proceed();
    }

    /**
     * 配置通用更新方法
     *
     * @param parameter
     */
    private void initUpdateMethod(Object parameter) {
        if (parameter instanceof UpdaterSetterImpl) {
            UserEntity user = UserContext.getUserEntity();
            if (null != user) {
                UpdaterSetterImpl setter = (UpdaterSetterImpl) parameter;
                setter.setUpdaterId(user.getUserId());
                setter.setUpdaterName(user.getUsername());
                setter.setUpdateTime(new Date());
            }
        }
    }

    /**
     * 配置通用新增方法
     *
     * @param parameter
     */
    private void initSaveMethod(Object parameter) {
        if (parameter instanceof BaseEntity) {
            Log4jUtils.getInstance(getClass()).debug("配置通用持久化变量");

            BaseEntity baseEntity = (BaseEntity) parameter;
            baseEntity.setId(IdWorker.getIdStr());
            baseEntity.setIsDeleted(0);
            baseEntity.setCreateTime(new Date());
        }

        if (parameter instanceof CreatorSetterImpl) {
            Log4jUtils.getInstance(getClass()).debug("配置创建人信息");
            UserEntity user = UserContext.getUserEntity();
            if (null != user) {
                CreatorSetterImpl setter = (CreatorSetterImpl) parameter;
                setter.setCreatorId(user.getUserId());
                setter.setCreatorName(user.getUsername());
            }
        }
    }


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

    @Override
    public void setProperties(Properties properties) {

    }
}
在Myabtis配置中加入拦截器
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <!--配置全局变量 -->
    <settings>
        <!-- jdbc用getGeneratedKeys 获取数据库自增键值 -->
        <setting name="useGeneratedKeys" value="true" />
        <!-- 使用列别名替代列名 select name as title from table -->
        <setting name="useColumnLabel" value="true" />
        <!-- 开启驼峰命名法: Table(create_time) ->createTime -->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>

    <plugins>
        <plugin interceptor="com.example.oldguy.modules.commons.interceptors.BaseEntityMapperInterceptor"/>
        <!--<plugin interceptor="com.example.oldguy.modules.commons.interceptors.BaseEntityInterceptor"/>-->
        <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"/>
    </plugins>

</configuration>
上一篇下一篇

猜你喜欢

热点阅读