首页 > 其他分享 >通用 Mapper 的批量插入实现

通用 Mapper 的批量插入实现

时间:2023-05-22 09:55:07浏览次数:41  
标签:tmp Mapper SqlHelper 批量 column 插入 sql null append

具体的 SQL 模板实现如下所示:

import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.MapperException;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.SelectKeyHelper;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
import tk.mybatis.mapper.provider.base.BaseInsertProvider;

import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author lxh
 */
public class GoodsInsertProvider extends BaseInsertProvider {

    public GoodsInsertProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
        super(mapperClass, mapperHelper);
    }

    protected final static String VAR_REGEX = "#\\{(.+)}";

    public String saveAll(MappedStatement ms) {
        Class<?> entityClass = getEntityClass(ms);
        StringBuilder sql = new StringBuilder();
        //获取全部列
        Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass);
        EntityColumn logicDeleteColumn = SqlHelper.getLogicDeleteColumn(entityClass);
        sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass)));
        sql.append(SqlHelper.insertColumns(entityClass, false, false, false));
        sql.append("<trim prefix=\"VALUES \" suffixOverrides=\",\">");
        sql.append("<foreach collection=\"collection\" item=\"item\" separator=\",\" >");
        processKey(sql, entityClass, ms, columnList);
        sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
        for (EntityColumn column : columnList) {
            if (!column.isInsertable()) {
                continue;
            }
            if (logicDeleteColumn != null && logicDeleteColumn == column) {
                sql.append(SqlHelper.getLogicDeletedValue(column, false)).append(",");
                continue;
            }
            String tmp;
            //优先使用传入的属性值,当原属性property!=null时,用原属性
            //自增的情况下,如果默认有值,就会备份到property_cache中,所以这里需要先判断备份的值是否存在
            //其他情况值仍然存在原property中
            if (column.isIdentity()) {
                tmp = SqlHelper.getIfCacheNotNull(column,
                        column.getColumnHolder(null, "_cache", ","));
                sql.append(tmp);
            } else {
                //其他情况值仍然存在原property中
                tmp = SqlHelper.getIfNotNull(column,
                        column.getColumnHolder(null, null, ","), isNotEmpty());
                sql.append(replaceByRegex(tmp, VAR_REGEX, "item.", true));
            }
            // tmp = SqlHelper.getIfNotNull(column,
            //        column.getColumnHolder(null, null, ","), isNotEmpty());

            //当属性为null时,如果存在主键策略,会自动获取值,如果不存在,则使用null
            //当null的时候,如果不指定jdbcType,oracle可能会报异常,指定VARCHAR不影响其他
            if (column.isIdentity()) {
                tmp = SqlHelper.getIfCacheIsNull(column, column.getColumnHolder() + ",");
                sql.append(replaceByRegex(tmp, "#\\{(.+})", "item.", true));
            } else {
                //当null的时候,如果不指定jdbcType,oracle可能会报异常,指定VARCHAR不影响其他
                tmp = SqlHelper.getIfIsNull(column,
                        column.getColumnHolder(null, null, ","), isNotEmpty());
                sql.append(replaceByRegex(tmp, VAR_REGEX, "item.", true));
            }
            // tmp = SqlHelper.getIfIsNull(column,
            //        column.getColumnHolder(null, null, ","), isNotEmpty());
        }
        sql.append("</trim>");
        sql.append("</foreach>");
        sql.append("</trim>");
        return sql.toString();
    }

    protected void processKey(StringBuilder sql, Class<?> entityClass,
                              MappedStatement ms, Set<EntityColumn> columnList) {
        //Identity列只能有一个
        boolean hasIdentityKey = false;
        //先处理cache或bind节点
        for (EntityColumn column : columnList) {
            if (column.isIdentity()) {
                //这种情况下,如果原先的字段有值,需要先缓存起来,否则就一定会使用自动增长
                //这是一个bind节点
                String tmp = SqlHelper.getBindCache(column);
                sql.append(replaceByRegex(tmp, "value=\"(.+\")", "item.", true));
                //如果是Identity列,就需要插入selectKey
                //如果已经存在Identity列,抛出异常
                if (hasIdentityKey) {
                    //jdbc类型只需要添加一次
                    if (column.getGenerator() != null && "JDBC".equals(column.getGenerator())) {
                        continue;
                    }
                    throw new MapperException(ms.getId() + "对应的实体类"
                            + entityClass.getName() + "中包含多个MySql的自动增长列,最多只能有一个!");
                }
                //插入selectKey
                SelectKeyHelper.newSelectKeyMappedStatement(ms, column, entityClass, isBEFORE(), getIDENTITY(column));
                hasIdentityKey = true;
            } else if (column.getGenIdClass() != null) {
                sql.append("<bind name=\"").append(column.getColumn())
                        .append("GenIdBind\" value=\"@tk.mybatis.mapper.genid.GenIdUtil@genId(");
                sql.append("item").append(", '").append(column.getProperty()).append("'");
                sql.append(", @").append(column.getGenIdClass().getName()).append("@class");
                sql.append(", '").append(tableName(entityClass)).append("'");
                sql.append(", '").append(column.getColumn()).append("')");
                sql.append("\"/>");
            }
        }
    }

    public static String replaceByRegex(String rawStr, String regex,
                                        String content, boolean et) {
        if (rawStr == null || rawStr.isEmpty()) {
            return rawStr;
        }
        if (!et) {
            return rawStr.replaceAll(regex, content);
        }

        Pattern pat = Pattern.compile(regex);
        Matcher matcher = pat.matcher(rawStr);
        while (matcher.find()) {
            if (matcher.groupCount() >= 1) {
                String group = matcher.group(1);
                rawStr = rawStr.replace(group, content + group);
            }
        }
        return rawStr;
    }
}

标签:tmp,Mapper,SqlHelper,批量,column,插入,sql,null,append
From: https://www.cnblogs.com/FatalFlower/p/17419812.html

相关文章

  • mycat linux 搭建,分表分库,增长长插入
    下载Mycat-server-1.6.7.1-release-20200209222254-linux.tar下载地址:Mycat-server-1.6.7.1-release-20200209222254-linux.tar解压进入bin启动./mycatstart启动./mycatstop停止./mycatrestart重启mycat分库分表server.xml<?xmlversion="1.0"encoding="UTF-8&qu......
  • springboot+mybatis逆向生成xxxmapper+xxxmapper.xml和xxx实体类
    1.新建springboot工程pom文件如下<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="ht......
  • Word批量修改图片环绕方式与尺寸大小
    前提:一份Word文档里面有100张图片,有大有小,需要将100张图片更改为统一大小,宽度与高度均为5厘米,同时环绕方式也需要改成四周型。默认Word图片的默认环绕方式为嵌入型,需要统一更改为四周型,然后才能批量更改大小,而批量更改大小方式需要使用VBA代码。第一步:打开 Word文档,并按下Alt+......
  • Common Lisp 批量处理生成HTML网页
    在组织磁盘文件的时候,想到HTMLweb的超级链接对知识有帮助,利用书籍《 PracticalCommonLisp》中的可移植的文件系统库。实现了遍历e盘的图像文件夹,生成多个网页文件,并收集所有的html后缀文件生成超链接。知识点:HTML编辑,文件系统遍历,CommonLisp宏代码如下: (defparamete......
  • 在Centos7上安装PXE装机环境来批量安装操作系统
    步骤1:安装必要的软件包首先,需要确保系统已安装dhcp、tftp-server和httpd等软件包。可以使用以下命令进行安装:yuminstall-ydhcptftp-serverhttpdsyslinux-tftpbootxinetd步骤2:配置DHCP服务器接下来,需要配置DHCP服务器以向客户端分配IP地址。在/etc/dhcp/d......
  • MySQL 插入数据
    MySQL插入数据MySQL表中使用INSERTINTOSQL语句来插入数据。你可以通过mysql>命令提示窗口中向数据表中插入数据,或者通过PHP脚本来插入数据。语法以下为向MySQL数据表插入数据通用的INSERTINTO SQL语法:INSERTINTOtable_name(field1,field2,...fieldN)......
  • python批量处理excel数据、批量透视、合并透视表
    ###t+21importpandasaspdimportos#半自动———#——<创建好格式文件夹#——<数据下载至文件夹#——<修改date#——<运行##直播时间date='4.21'#读取存放文件路径read_path='E:/test/t+21/'+date+'/1原始数据'path_list=os.listdir(read_path)pathdir=''writ......
  • Chrome浏览器好用的插件(批量保存所有选项卡网址、批量打开粘贴板网址插件)
    转自:https://www.cnblogs.com/nmap/p/6557883.html 1、Chrome批量保存所有选项卡网址+批量打开复制网址小插件批量保存所有选项卡网址插件:CopyAllUrls经常搜索一些东西,下班时无法处理完所有网页内容,比如做笔记什么的,又不舍得关闭网页。每个页面关闭前复制链接保存太麻烦......
  • 插入排序Java版
    插入排序工作原理:从头开始遍历数组,如果发现当前项比前一项小,说明当前项应该插到前面,交换一下即可。利用双层for循环,第一层是遍历整个数组,第二层负责遍历当前所遍历到的位置之前的数组。/***@Author:翰林猿*@Description:插入排序**/publicclassInsert{  pu......
  • 解决mysql自动插入的日期时间和现在的时间不一致的问题(基于docker)
    新建表的时候发现插入的时间还是早上 先查看配置文件的对不对 配置文件没问题问题只能出在服务器了,连上Linux 查看本机的时间没问题进入容器dockerexec-itmysql./bin/bash 日期明显有问题了进入mysqlmysql-uroot-pshowglobalvariabl......