基于 MybatisPlus 逻辑删除开启情况下兼容多数据库实现批量插入更新通用流程实现

基于 MybatisPlus 逻辑删除开启情况下兼容多数据库实现批量插入更新通用流程实现

背景

  • 项目上业务流程有大量使用 mysql 批量插入更新语法 insert on duplicate update
  • 由于现在公司业务需要,同时兼容达梦数据库使用,达梦数据库虽然也有类似的语法,不过使用起来也比较麻烦,生成相应的 SQL 可以看我这一篇文章

核心问题

  1. MySQL 更新插入流程如何使用实现?
  2. 如何实现多个数据库兼容插入更新的流程?
  3. 如何编写工具类优雅实现插入通用流程封装以及整合 MybatisPlus lambda 表达式查询,达到方便易用的效果?
  4. 开启 MybatisPlus 逻辑删除功能,怎么通过自定义 SQL 查询出所有数据(插入更新流程可能涉及到所有的数据,并不是只是处理未逻辑删除的数据)?
  5. 批量数据插入更新速度如何优化?

代码实现

实现多数据库兼容插入更新操作,只能根据 MySQL 插入更新原理利用代码抽象通用化流程,较好的通用化方式是使用 MybatisPlus 自带的通用 CRUD 逻辑方法实现,但是原有自带方法开启逻辑删除功能以后,查询方法都会自带过滤逻辑删除的数据,需要实现自定义 SQL 注入器,为了实现一套不带逻辑删除的通用方法

  • MySQL 插入更新原理
  • MybatisPlus 逻辑删除功能
  • 自定义 SQL 注入器相关教程

拓展自定义 SQL 注入器实现

新增自定义方法

SelectList 方法不带逻辑删除

public class SelectListWithoutLogicDelete extends AbstractMethod {
   

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
   
        String sql = String.format(
                SqlMethod.SELECT_LIST.getSql(),
                sqlFirst(),
                sqlSelectColumns(tableInfo, true),
                tableInfo.getTableName(),
                sqlWhereEntityWrapper(true, tableInfo),
                sqlComment()
        );

        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);

        String mapperMethodName = StrUtil.lowerFirst(getClass().getSimpleName());
        return addSelectMappedStatementForTable(mapperClass, mapperMethodName, sqlSource, tableInfo);
    }

    // 重写 sqlWhereEntityWrapper ,去掉逻辑删除相关代码
    @Override
    protected String sqlWhereEntityWrapper(boolean newLine, TableInfo table) {
   
        String sqlScript = table.getAllSqlWhere(false, true, WRAPPER_ENTITY_DOT);
        sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", WRAPPER_ENTITY), true);
        sqlScript += NEWLINE;
        sqlScript += SqlScriptUtils.convertIf(String.format(SqlScriptUtils.convertIf(" AND", String.format("%s and %s", WRAPPER_NONEMPTYOFENTITY, WRAPPER_NONEMPTYOFNORMAL), false) + " ${%s}", WRAPPER_SQLSEGMENT),
                String.format("%s != null and %s != '' and %s", WRAPPER_SQLSEGMENT, WRAPPER_SQLSEGMENT,
                        WRAPPER_NONEMPTYOFWHERE), true);
        sqlScript = SqlScriptUtils.convertWhere(sqlScript) + NEWLINE;
        sqlScript += SqlScriptUtils.convertIf(String.format(" ${%s}", WRAPPER_SQLSEGMENT),
                String.format("%s != null and %s != '' and %s", WRAPPER_SQLSEGMENT, WRAPPER_SQLSEGMENT,
                        WRAPPER_EMPTYOFWHERE), true);
        sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", WRAPPER), true);
        return newLine ? NEWLINE + sqlScript : sqlScript;
    }
}

UpdateById 方法不带逻辑删除

public class UpdateByIdWithoutLogicDelete extends AbstractMethod {
   
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
   
        SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID;

        final String additional = optlockVersion(tableInfo);
        String sql = String.format(
                sqlMethod.getSql(),
                tableInfo.getTableName(),
                // 搬运 UpdateById 代码,第一个参数变化了
                sqlSet(false, false, tableInfo, false, ENTITY, ENTITY_DOT),
                tableInfo.getKeyColumn(),
                ENTITY_DOT + tableInfo.getKeyProperty(),
                additional
        );

        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        String mapperMethodName = StrUtil.lowerFirst(getClass().getSimpleName());
        return addUpdateMappedStatement(mapperClass, modelClass, mapperMethodName, sqlSource);
    }
}
注入不带逻辑删除自定义 mapper 方法
public class SqlInjectorExtension extends DefaultSqlInjector {
   
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
   
        List<AbstractMethod> methods = super.getMethodList(mapperClass);
        // 原来基础上注入两个新方法
        methods.add(new SelectListWithoutLogicDelete());
        methods.add(new UpdateByIdWithoutLogicDelete());
        return methods;
    }
}

封装自定义 mapper

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.

你可能感兴趣的:(mybatis,mysql,mybatis,plus,插入更新,达梦,sql,注入器)