Mybatis(拦截器实现)通用mapper及全ORM实现(二)

本文详细介绍了如何使用Mybatis拦截器实现通用Mapper和全ORM操作。通过拦截器,针对`prepare`、`update`、`handleResultSets`方法进行拦截,实现了SQL语句的动态修改、参数设置和结果封装。文中以添加单个实体为例,讲解了拦截器的工作流程,包括获取MetaObject、构建SQL、设置参数等步骤。下篇文章将介绍TableInfo类及其在拦截器中的应用。
摘要由CSDN通过智能技术生成

上一篇简单介绍了一下mybatisext的基本使用情况,接下来我们开始陆续介绍一下实现

先看一下mapper基类:

package cw.frame.mybatisext.base;

import cw.frame.mybatisext.SqlStatement;
import cw.frame.mybatisext.base.entity.BaseExtEntity;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface BaseExtMapper<Entity extends BaseExtEntity> {

    @Insert(BaseSqlStatement.OPERATE_TYPE_ADD_ONE)
    public int addOne(@Param(BaseSqlStatement.OPERATE_PARAM_ENTITY) Entity entity);

    @Insert(BaseSqlStatement.OPERATE_TYPE_ADD_MANY)
    public int addMany(@Param(BaseSqlStatement.OPERATE_PARAM_ENTITIES) List<Entity> entities);

    @Delete(BaseSqlStatement.OPERATE_TYPE_REMOVE_BY_ID)
    public int removeById(@Param(BaseSqlStatement.OPERATE_PARAM_PRIMARY_KEY) Object id);

    @Delete(BaseSqlStatement.OPERATE_TYPE_REMOVE_BY_IDS)
    public int removeByIds(@Param(BaseSqlStatement.OPERATE_PARAM_PRIMARY_KEYS) List<Object> ids);

    @Delete(BaseSqlStatement.OPERATE_TYPE_REMOVE)
    public int remove(@Param(BaseSqlStatement.OPERATE_PARAM_SQLSTATEMANT) SqlStatement sqlStatement);

    @Update(BaseSqlStatement.OPERATE_TYPE_UPDAT_BY_ID)
    public int updateById(@Param(BaseSqlStatement.OPERATE_PARAM_ENTITY) Entity entity);

    @Update(BaseSqlStatement.OPERATE_TYPE_UPDATE)
    public int update(@Param(BaseSqlStatement.OPERATE_PARAM_SQLSTATEMANT) SqlStatement sqlStatement);

    @Select(BaseSqlStatement.OPERATE_TYPE_GET_BY_ID)
    public Entity getById(@Param(BaseSqlStatement.OPERATE_PARAM_PRIMARY_KEY) Object id);

    @Select(BaseSqlStatement.OPERATE_TYPE_GET_BY_IDS)
    public List<Entity> getByIds(@Param(BaseSqlStatement.OPERATE_PARAM_PRIMARY_KEYS) List<Object> ids);

    @Select(BaseSqlStatement.OPERATE_TYPE_GET_ONE)
    public Entity getOne(@Param(BaseSqlStatement.OPERATE_PARAM_SQLSTATEMANT) SqlStatement sqlStatement);

    @Select(BaseSqlStatement.OPERATE_TYPE_GET_MANY)
    public List<Entity> getMany(@Param(BaseSqlStatement.OPERATE_PARAM_SQLSTATEMANT) SqlStatement sqlStatement);

    @Select(BaseSqlStatement.OPERATE_TYPE_GET_PAGE)
    public List<Entity> getPage(@Param(BaseSqlStatement.OPERATE_PARAM_SQLSTATEMANT) SqlStatement sqlStatement, @Param(BaseSqlStatement.OPERATE_PARAM_PAGER) Pager pager);

}

这里定义了一些方法,其中SQL语句都是固定的常量,也就是后续需要通过mybatis拦截器根据范型实体类来做修改
SqlStatement是一个查询对象,后面再介绍

接下来我们看下拦截器的实现,首先看下拦截器代码:

package cw.frame.mybatisext.provider.mysql;

import cw.frame.mybatisext.provider.mysql.interceptorhandler.ResultSetHandlerInterceptor;
import cw.frame.mybatisext.provider.mysql.interceptorhandler.StatementHandlerInterceptor;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;

import java.sql.Connection;
import java.sql.Statement;
import java.util.*;

@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
        @Signature(type = StatementHandler.class, method = "update", args = Statement.class),
        @Signature(type = ResultSetHandler.class, method="handleResultSets", args={Statement.class})
})
public class MySqlInterceptor implements Interceptor {
    private StatementHandlerInterceptor statementHandlerInterceptor;
    private ResultSetHandlerInterceptor resultSetHandlerInterceptor;

    @Override
    public Object intercept(Invocation invocation) throws Throwable{
        // query/update -> prepare -> setParameters -> handleResultSets

        Object target = invocation.getTarget();
        String methodName = invocation.getMethod().getName();

        if (target instanceof StatementHandler && methodName == "prepare"){
            return this.getStatementHandlerInterceptor().prepare(invocation);
        } else if (target instanceof StatementHandler && methodName == "update"){
            return this.getStatementHandlerInterceptor().update(invocation);
        } else if (target instanceof ResultSetHandler && methodName == "handleResultSets"){
            return this.getResultSetHandlerInterceptor().handleResultSets(invocation);
        }

        return invocation.proceed();
    }

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

    @Override
    public void setProperties(Properties properties) {
    }

    private StatementHandlerInterceptor getStatementHandlerInterceptor() {
        if (this.statementHandlerInterceptor == null){
            this.statementHandlerInterceptor = new StatementHandlerInterceptor();
        }

        return this.statementHandlerInterceptor;
    }

    private ResultSetHandlerInterceptor getResultSetHandlerInterceptor() {
        if (this.resultSetHandlerInterceptor == null){
            this.resultSetHandlerInterceptor = new ResultSetHandlerInterceptor();
        }

        return this.resultSetHandlerInterceptor;
    }
}

因为目前我只实现了mysql数据库操作,所以这个拦截器是在cw.frame.mybatisext.provider.mysql包下,相应的查询对象等都是在这个包下

mybatis的拦截器可以拦截的几个方法也是整个数据操作的一个流程:query/update -> prepare -> setParameters -> handleResultSets,根据我们的需求,我们相应要做的就是:
1、修改sql语句
2、设置参数
3、封装返回结果
所以我这里针对了prepare、update、handleResultSets这三个方法进行拦截,设置参数我放在了prepare里

我们先看下prepare、updat的拦截实现,他们在StatementHandlerInterceptor中,代码稍有点长了,没耐心的可以先略过

package cw.frame.mybatisext.provider.mysql.interceptorhandler;

import cw.frame.mybatisext.SqlStatement;
import cw.frame.mybatisext.base.BaseSqlStatement;
import cw.frame.mybatisext.base.FormatSqlWrapper;
import cw.frame.mybatisext.base.Pager;
import cw.frame.mybatisext.base.entity.BaseExtEntity;
import cw.frame.mybatisext.base.entity.BaseExtEnum;
import cw.frame.mybatisext.base.entity.ColumnInfo;
import cw.frame.mybatisext.base.entity.TableInfo;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Invocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.PreparedStateme
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值