上一篇简单介绍了一下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