• 再数据同步或者幂等场景下,常常需要设置唯一索引来避免重复请求, select and update 效率低,且并发时还是会报错,并不友好,那么可以用Mysql的Insert ignore语法来优化。
  • MybatisPlus官方并没有针此处场景进行支持
  • <dependency>
    	<groupId>com.baomidou</groupId>
    	<artifactId>mybatis-plus-boot-starter</artifactId>
    	<version>3.2.0</version>
    	<exclusions>
    		<exclusion>
    			<groupId>com.baomidou</groupId>
    			<artifactId>mybatis-plus-generator</artifactId>
    		</exclusion>
    	</exclusions>
    </dependency>
    

    三、注入自定义批量插入sql

    因为只需要改造insertBatchSomeColumn方法,那直接CV就好

    insertBatchSomeColumn方法属于mybatis plus官方扩展包

  • sql模板
  • public class InsertIgnoreBatchAllColumn extends AbstractMethod {
         * mapper 对应的方法名
        private static final String MAPPER_METHOD = "insertIgnoreBatchAllColumn";
         * 字段筛选条件
        @Setter
        @Accessors(chain = true)
        private Predicate<TableFieldInfo> predicate;
        @SuppressWarnings("Duplicates")
        @Override
        public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
            KeyGenerator keyGenerator = new NoKeyGenerator();
            SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
            String sqlTemplate = "<script>\nINSERT IGNORE INTO %s %s VALUES %s\n</script>";
            List<TableFieldInfo> fieldList = tableInfo.getFieldList();
            String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(false) +
                this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);
            String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;
            String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(ENTITY_DOT, false) +
                this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);
            insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;
            String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);
            String keyProperty = null;
            String keyColumn = null;
            // 表包含主键处理逻辑,如果不包含主键当普通字段处理
            if (StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
                if (tableInfo.getIdType() == IdType.AUTO) {
                    /* 自增主键 */
                    keyGenerator = new Jdbc3KeyGenerator();
                    keyProperty = tableInfo.getKeyProperty();
                    keyColumn = tableInfo.getKeyColumn();
                } else {
                    if (null != tableInfo.getKeySequence()) {
                        keyGenerator = TableInfoHelper.genKeyGenerator(tableInfo, builderAssistant, sqlMethod.getMethod(), languageDriver);
                        keyProperty = tableInfo.getKeyProperty();
                        keyColumn = tableInfo.getKeyColumn();
            String sql = String.format(sqlTemplate, tableInfo.getTableName(), columnScript, valuesScript);
            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
            return this.addInsertMappedStatement(mapperClass, modelClass, MAPPER_METHOD, sqlSource, keyGenerator, keyProperty, keyColumn);
     
  • 注入sql
  • public class CustomerSqlInjector extends DefaultSqlInjector {
        @Override
        public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
            List<AbstractMethod> methodList = super.getMethodList(mapperClass);
            methodList.add(new InsertIgnoreBatchAllColumn());
            return methodList;
     
  • 通用mapper
  • public interface CommonMapper<T> extends BaseMapper<T> {
         * 全量插入,等价于insert,忽略唯一索引冲突的行
         * {@link InsertIgnoreBatchAllColumn}
         * @param entityList
         * @return
        int insertIgnoreBatchAllColumn(List<T> entityList);
     
  • 通用Service
  • public class CommonServiceImpl<M extends CommonMapper<T>, T> extends ServiceImpl<M, T> {
        @Transactional(rollbackFor = Exception.class)
        public boolean fastSaveIgnoreBatch(List<T> list, int batchSize) {
            if(CollectionUtils.isEmpty(list)) {
                return true;
            batchSize = batchSize < 1 ? BATCH_SIZE : batchSize;
            if(list.size() <= batchSize) {
                return retBool(baseMapper.insertIgnoreBatchAllColumn(list));
            for (int fromIdx = 0 , endIdx = batchSize ; ; fromIdx += batchSize, endIdx += batchSize) {
                if(endIdx > list.size()) {
                    endIdx = list.size();
                baseMapper.insertIgnoreBatchAllColumn(list.subList(fromIdx, endIdx));
                if(endIdx == list.size()) {
                    return true;
    	@Transactional(rollbackFor = Exception.class)
        public boolean fastSaveIgnoreBatch(List<T> list) {
            return fastSaveIgnoreBatch(list, BATCH_SIZE);
                                                        开源日报 | 通用端到端OCR模型开源;Cassandra 5.0正式GA;NGINX迁移到GitHub;iPhone 16全系列配备8GB RAM;国产数据库100%替代走到哪了?
                                                        NGINX 项目迁移到 GitHub
                                                        完整的数仓能力,字节云原生开源数仓 ByConity 1.0 版本发布!
                                                        Redox OS 0.9.0 版本发布:开源操作系统迎来重大更新
                                                        当《黑神话:悟空》遇上 openKylin,国产力量的极致碰撞!
                                                        PublicCMS 202406.e 更新,新增字体加密敏感词替换等
                                                        开源 OA 办公系统 — 勾股 OA 5.1.2 新版发布
                                                        Xinference v0.15.0 版本飞跃:自定义模型能力再升级,重塑 AI 交互体验
                                                        Rust 日志库 tklog v0.2.0 :支持设置日志级别独立日志文件
                                                        别再 mybatis 了,融合 JPA 和超强查询的 sqltoy-orm 5.6.22 发版
                                                        :fire::fire::fire:超级 ORM 框架 mybatis-mp 1.6.7 正式发布
                                                        Apple Intelligence 将于下月起登陆 iPhone、iPad 与 Mac
                                                        Apache Cassandra 5.0 正式 GA,带来向量搜索、JDK 17 支持、存储附加索引等功能
                                                        Apple 推出 iPhone 16 系列新产品
                                                        【视频】Solon Cloud Gateway: Helloworld (代理 Solon 官网)
                                                        域名证书检测平台 Domain Admin 加入 Dromara 开源社区
                                                          ActiveReports 报表应用教程 (15)---报表换肤 
                                                          Html5 FileReader 对文件进行Base64编码 
                                                          Wijmo 更优美的jQuery UI部件集:通过jsFiddle测试Wijmo Gauges 
                                                          ActiveReports 报表应用教程 (8)---交互式报表之动态过滤 
                                                          ActiveReports 报表应用教程 (16)---报表导出 
                                                        C#性能优化实践
                                                          ActiveReports 报表应用教程 (7)---交叉报表及数据透视图实现方案 
                                                          2013 北京 QCon热点分享 
                                                          ActiveReports 报表应用教程 (9)---交互式报表之动态排序 
                                                          ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view) 
                                                          Spread for Windows Forms快速入门(4)---常用的单元格类型(上) 
                                                          带你走近AngularJS - 基本功能介绍 
                                                          如何选择高性价比的控件产品 
                                                          Table-values parameter(TVP)系列之三: 利用Collection将其作为参数传给SP 
                                                          TX Text Control文字处理教程(4)标记文本域 
                                                          分享自制的C#和VB Code互转工具 
                                                          程序员级别鉴定书(.NET面试问答集锦) 
                                                          ActiveReports 报表应用教程 (14)---数据可视化 
                                                          TechED2010与我(一)―― 初来乍到 
                                                          Silverlight 5 深入理解 - TechEd2011葡萄城讲师课程 
                                                        基于Html5的Canvas实现的Clocks (钟表)
                                                          如何遍历当前进程中的AppDomain 
                                                          第十一届GPCT杯大学生程序设计大赛完美闭幕 
                                                          如何在ASP.NET中生成HTML5离线Web应用 
                                                        开发了一个一起听歌聊天的开源项目
                                                          分享自制的C#和VB Code互转工具 
                                                        也许跟大家不太一样,我是这么用TypeScript来写前端的
                                                        用SwiftUI开发了一个Gitee在iOS上的App
                                                        不太一样的前端开发之TypeScript装饰器和面向对象
                                                          如何在ASP.NET中生成HTML5离线Web应用 
                                                          Silverlight自定义数据绑定控件应该如何处理IEditableObject和IEditableCollectionView对象 
                                                          MultiRow中文版技术白皮书 
                                                          2013 北京 QCon热点分享 
                                                          如何把Excel中的单元格等对象保存成图片 
                                                          MultiRow发现之旅(一)- 高效模板设计器 
                                                          Spread for Windows Forms快速入门(13)---数据排序 
                                                          Spread for Windows Forms快速入门(5)---常用的单元格类型(下) 
                                                          如何雇人的十五条建议 
                                                        vscode成功变身社交平台?看我如何给vscode扩展一个聊天室!
                                                          Spread for Windows Forms快速入门(15)---使用 Spread 设计器 
                                                          在 ActiveReports 中嵌入 Spread 控件 
                                                          MultiRow发现之旅(五)- MultiRow版俄罗斯方块(exe + 源码) 
                                                          “云”随我动近在咫尺 - 中小企业如何看待云计算? 
                                                          用于 Windows8 的 Wijmo Charts 图表控件 
                                                          如何把Excel中的单元格等对象保存成图片 
                                                        新写了一个基于MacOS设计的WebUI
                                                        用代码聊聊我们跟目前主流前端编程不一样的地方
                                                        SwiftUI在iOS上NavigationBar标题重影问题复现
                                                          TX Text Control文字处理教程(2)- 文件操作 
                                                          TechED2010与我(一)―― 初来乍到 
                                                        在 ActiveReports 中嵌入 Spread 控件
                                                          一套内容采集系统 解放编辑人员 
                                                        BBBUG音乐聊天室的开发故事和架构设计
                                                          【技术维新 践行精彩】移动互联时代的研发利器 
                                                          分享ISTQB培训体验 
                                                          Spread for Windows Forms高级主题(7)---自定义打印的外观 
                                                          Wijmo 更优美的jQuery UI部件集:运行时处理Wijmo GridView数据操作 
                                                          MultiRow发现之旅(一)- 高效模板设计器 
                                                        Nginx反向代理其他站并替换关键词遇到的坑
                                                        基于装饰器-我又是这么用TypeScript处理表格配置的
                                                        域名-DDNS-内网穿透-端口转发-DNS的一些小常识
                                                        在Silverlight中动态绑定页面报表(PageReport)的数据源
                                                          Spread for Windows Forms高级主题(6)---数据绑定管理 
                                                        免装软件和服务,使用SSH实现内网穿透并反向代理
                                                          ActiveReports 报表应用教程 (15)---报表换肤 
                                                        基于装饰器-我是这么处理TypeScript项目数据转换的
                                                          应用系统中常见报表类型解析 
                                                          TX Text Control文字处理教程(7)邮件合并 
                                                          ASP.NET MVC 5 - 查询Details和Delete方法 
                                                          Spread for Windows Forms高级主题(1)---底层模型 
                                                        Nginx实现Java服务API接口的开发阶段高可用
                                                          Spread for Windows Forms高级主题(4)---自定义用户交互 
                                                        Wijmo 更优美的jQuery UI部件集:爱上 ThemeRoller
                                                          Spread for Windows Forms快速入门(7)---单元格的交互操作 
                                                          ASP.NET MVC 5 - 给电影表和模型添加新字段 
                                                          响应式设计(Response Web Design)浅谈 
                                                          Spread for Windows Forms快速入门(13)---数据排序 
                                                          TX Text Control文字处理教程(13)实现拖放操作 
                                                          Spread for WinRT 7新功能使用指南 
                                                          WPF的消息机制(三)- WPF内部的5个窗口之处理激活和关闭的消息窗口以及系统资源通知窗口