前言
MP在一开始就给大家提供了很多通用的方法,在DefaultSqlInjector这个类中,在MethodList这个集合当中包含的都是通用方法类,如果想要使用自定义通用方法,也需要添加到这个集合当中。
/**
* SQL 默认注入器
*
* @author hubin
* @since 2018-04-10
*/
public class DefaultSqlInjector extends AbstractSqlInjector {
@Override
public List<AbstractMethod> getMethodList() {
return Stream.of(
new Insert(),
new Delete(),
new DeleteByMap(),
new DeleteById(),
new DeleteBatchByIds(),
new Update(),
new UpdateById(),
new SelectById(),
new SelectBatchByIds(),
new SelectByMap(),
new SelectOne(),
new SelectCount(),
new SelectMaps(),
new SelectMapsPage(),
new SelectObjs(),
new SelectList(),
new SelectPage()
).collect(toList());
}
}
实现自定义方法-以删除时填充为例:
- 创建自定义方法的类
- 类名是DelFillUserMethod,这个是自定义的,但是最好是见名知意的类名。
- 继承AbstractMethod抽象类,AbstractMethod是抽象的注入方法类,每个通用方法也都继承了这个类,也是为了方便调用里面的方法
- 重写injectMappedStatement方法,injectMappedStatement内是我们完成我们这个方法具体的逻辑。
- CustomSqlMethod是自定义的枚举类,我在下面已经贴出来了,这样可以使代码更优雅,我没有选择用官方提供的SqlMethod,是因为我怕到时候不容易维护,所以写了一个自己的,这个全看个人😄。
- 具体内容我在代码中也有注释。
/**
* @auther: zpq
* @date: 2020/11/9 19:55
* @description: 删除并填充删除人信息
*/
public class DelFillUserMethod extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(
Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
// 获取用户信息
String userId = UserContext.getCurrent() == null ? null : UserContext.getCurrent().getId2();
String userName = UserContext.getCurrent() == null ? null : UserContext.getCurrent().getName();
// set 语句
String set = "set useflag = 0,deletetime = now(),operatetime = now()";
if (StringUtils.isNotBlank(userId)) set += ",set deleterid = " + userId;
if (StringUtils.isNotBlank(userName)) set += ",set deleter = " + userName;
// 拿到我们定义好的枚举
CustomSqlMethod sqlMethod = CustomSqlMethod.DEL_FILL_USER;
/** * 组装自己的sql */
String sql =
String.format(
// 定义好的sql
sqlMethod.getSql(),
// 表名
tableInfo.getTableName(),
// set 的值
set,
// 主键(数据库字段名)
tableInfo.getKeyColumn(),
// 实体类属性名
tableInfo.getKeyProperty(),
// and 主键 = yes | 如果是false的话就是 and 主键 = no
tableInfo.getLogicDeleteSql(true, true));
// 动态SQL标签处理器
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
// 交给mp大佬们处理执行
return addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
}
}
- CustomSqlMethod枚举类内容
/**
* @auther: zpq
* @date: 2020/11/10 14:29
* @description: 自定义通用sql与方法名称
*/
public enum CustomSqlMethod {
/**
* 插入
*/
INSERT_ONE("insert", "插入一条数据(选择字段插入)", "<script>\nINSERT INTO %s %s VALUES %s\n</script>"),
/**
* 删除
*/
DELETE_BY_ID("deleteById", "根据ID 删除一条数据", "<script>\nDELETE FROM %s WHERE %s=#{%s}\n</script>"),
/**
* 逻辑删除
*/
LOGIC_DELETE_BY_ID("deleteById", "根据ID 逻辑删除一条数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
/**
* 逻辑删除 -> 修改
*/
DEL_FILL_USER("delFillUser", "删除填充用户信息", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
BATCH_DEL_FILL_USER("batchDelFillUser", "批量删除填充用户信息", "<script>\nUPDATE %s %s WHERE %s IN (%s) %s\n</script>"),
/**
* 查询
*/
SELECT_OBJS("selectObjs", "查询满足条件所有数据", "<script>%s SELECT %s FROM %s %s %s\n</script>");
private final String method;
private final String desc;
private final String sql;
CustomSqlMethod(String method, String desc, String sql) {
this.method = method;
this.desc = desc;
this.sql = sql;
}
public String getMethod() {
return method;
}
public String getDesc() {
return desc;
}
public String getSql() {
return sql;
}
}
- 创建注入器,并把自定义的方法添加到集合当中。
- 类名是CustomSqlInjector,自定义的
- 继承DefaultSqlInjector并重写getMethodList,SQL 默认注入器上面也有提到过,我们得把我们自定义的方法加入到通用方法的集合
methodList
当中
/**
* @auther: zpq
* @date: 2020/11/9 20:00
* @description: 自定义sql注入器
* 把自定义的通用方法加入mp的方法集合
*/
@Component
public class CustomSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
// 这里很重要,先要通过父类方法,获取到原有的集合,不然会自带的通用方法会失效的
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
/***
* 添加自定义方法类
*/
methodList.add(new DelFillUserMethod());
methodList.add(new BatchDelFillUserMethod());
return methodList;
}
}
- 最后一步就是在*.dao.*Mapper中加入自定义方法 如下:
/**
* @Description: 删除并填充删除人信息
*
* @param: id 主键id
* @auther: zpq
* @date: 2020/11/10 11:47 上午
*/
int delFillUser(Serializable id);
- 其实以上就算完成了,但是如果同时有好几个Mapper需要用到这个自定义通用方法,这样可能不是那么优雅。
- 我们创建一个通用
SuperMapper
,然后继承BaseMapper,这样的话,用到这个方法的mapper只需要继承SuperMapper就可以了,如下:
/**
* @auther: zpq
* @date: 2020/11/9 20:10
* @description: 通用mapper
*/
public interface SuperMapper<T> extends BaseMapper<T> {
/**
* @Description: 删除并填充删除人信息
*
* @param: id 主键id
* @auther: zpq
* @date: 2020/11/10 11:47 上午
*/
int delFillUser(Serializable id);
/**
* @Description: 批量删除并填充删除人信息
*
* @param: idList 主键ID列表(不能为 null 以及 empty)
* @auther: zpq
* @date: 2020/11/10 3:12 下午
*/
int batchDelFillUser(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
}
- 你可能也已经发现自定义的批量操作的通用方法,我直接贴出来:
/**
* @auther: zpq
* @date: 2020/11/10 14:59
* @description: 批量删除填充用户信息
*/
public class BatchDelFillUserMethod extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(
Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
// 获取用户信息
String userId = UserContext.getCurrent() == null ? null : UserContext.getCurrent().getId2();
String userName = UserContext.getCurrent() == null ? null : UserContext.getCurrent().getName();
// 自己组装sql
String set = "set useflag = 0,deletetime = now(),operatetime = now()";
if (StringUtils.isNotBlank(userId)) set += ",set deleterid = " + userId;
if (StringUtils.isNotBlank(userName)) set += ",set deleter = " + userName;
// 拿到我们定义好的sql
CustomSqlMethod sqlMethod = CustomSqlMethod.BATCH_DEL_FILL_USER;
// 填充sql
String sql =
String.format(
sqlMethod.getSql(),
tableInfo.getTableName(),
set,
tableInfo.getKeyColumn(),
// foreach in(ids)
SqlScriptUtils.convertForeach("#{item}", COLLECTION, null, "item", COMMA),
tableInfo.getLogicDeleteSql(true, true));
// 动态SQL标签处理器
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
return addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
}
}
结束语:
到此mybatis-plus高级功能 实现自定义通用方法详解
就结束了,其实很简单,写其他方法也一样,对照着mybatis-plus源码照着抄就行哈哈哈。。。