目标:新增mysql下的 插入更新的语法

INSERT INTO %s %s VALUES %s ON DUPLICATE KEY UPDATE %s

新增方法类,新增的方法名称为insertOrUpdate和insertOrUpdateBatch方法,但其mapper层的方法名为insertOrUpdate方法

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource; import java.util.List;
import java.util.Objects; import static java.util.stream.Collectors.joining; public class InsertOrUpdate extends AbstractMethod { public InsertOrUpdate() {
super(MyBatisPlusMethod.INSERT_OR_UPDATE.getMethod());
} public InsertOrUpdate(String method) {
super(method);
} @Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
MyBatisPlusMethod sqlMethod = MyBatisPlusMethod.INSERT_OR_UPDATE;
String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf(ENTITY_DOT),
LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf(ENTITY_DOT),
LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
String setScript = SqlScriptUtils.convertTrim(this.getUpdateValuePart(tableInfo, ENTITY_DOT),
null, null, null, COMMA);
String keyProperty = null;
String keyColumn = null;
// 表包含主键处理逻辑,如果不包含主键当普通字段处理
if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
if (tableInfo.getIdType() == IdType.AUTO) {
/* 自增主键 */
keyGenerator = Jdbc3KeyGenerator.INSTANCE;
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
} else if (null != tableInfo.getKeySequence()) {
keyGenerator = TableInfoHelper.genKeyGenerator(this.methodName, tableInfo, builderAssistant);
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
}
}
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript, setScript);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);
} protected String getMethod(MyBatisPlusMethod sqlMethod) {
return StringUtils.isBlank(methodName) ? sqlMethod.getMethod() : this.methodName;
} protected String getUpdateValuePart(TableInfo tableInfo, String prefix) {
List<TableFieldInfo> fieldList = tableInfo.getFieldList();
return fieldList.stream().map(i -> i.getSqlSet(false, prefix))
.filter(Objects::nonNull).collect(joining(NEWLINE));
}
}

新增该方法的枚举类

public enum MyBatisPlusMethod {
/**
* 插入
*/
INSERT_OR_UPDATE("insertOrUpdate", "插入更新一条数据(选择字段插入)", "<script>\nINSERT INTO %s %s VALUES %s ON DUPLICATE KEY UPDATE %s\n</script>"); private final String method;
private final String desc;
private final String sql; MyBatisPlusMethod(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;
}
}

继承并实现MyBatisPlus的mapper、service层的方法

mapper

import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.chinacreator.c2.dao.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param; public interface MyBatisPlusMapper<T> extends BaseMapper<T> { /**
* 插入更新一条记录
*
* @param entity 实体对象
* @return
*/
int insertOrUpdate(@Param(Constants.ENTITY) T entity);
}

service

package com.chinacreator.c2.chs.mp;

import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.transaction.annotation.Transactional; import java.util.Collection; public interface MyBatisPlusService<T> extends IService<T> { /**
* 一句sql执行插入更新语句
*
* @param entityList 需要插入更新的实体
* @return 是否成功
*/
@Transactional(rollbackFor = Exception.class)
default boolean insertOrUpdateBatch(Collection<T> entityList) {
return insertOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
} boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize); /**
* 一句sql执行插入更新语句
*
* @param entity 需要插入更新的实体
* @return 是否成功
*/
boolean insertOrUpdate(T entity); }

serviceImpl

import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.apache.ibatis.binding.MapperMethod;
import org.springframework.transaction.annotation.Transactional; import java.util.Collection; public class MyBatisPlusServiceImpl<M extends MyBatisPlusMapper<T>, T> extends ServiceImpl<M, T> implements MyBatisPlusService<T> {
@Override
@Transactional(rollbackFor = Exception.class)
public boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) {
String mapperStatementId = mapperClass.getName() + StringPool.DOT + MyBatisPlusMethod.INSERT_OR_UPDATE.getMethod();
return SqlHelper.executeBatch(entityClass, log, entityList, batchSize, (sqlSession, entity) -> {
MapperMethod.ParamMap<Object> param = new MapperMethod.ParamMap<>();
param.put(Constants.ENTITY, entity);
sqlSession.insert(mapperStatementId, param);
});
} @Override
public boolean insertOrUpdate(T entity) {
return SqlHelper.retBool(getBaseMapper().insertOrUpdate(entity));
}
}

新增自定义的MyBatisPlus自定义注入器

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.chinacreator.c2.dao.mapper.InsertBatchMethod; import java.util.List; public class MyBatisPlusSqlInjector extends DefaultSqlInjector { /**
* 如果只需增加方法,保留mybatis plus自带方法, 可以先获取super.getMethodList(),再添加add
*/
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new InsertOrUpdate());
return methodList;
}
}

在MyBatisPlus的配置文件类上 创建该自定义注入器的bean对象

import com.chinacreator.c2.chs.mp.MyBatisPlusSqlInjector;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration; @Slf4j
@Configuration
public class MyBatisPlusConfig {
@Bean
public MyBatisPlusSqlInjector customizedSqlInjector() {
return new MyBatisPlusSqlInjector();
}
}

对使用官方生成的mapper、service、serviceImpl文件的继承类上改为我这边新增的

最后再调用service或mapper下的insertOrUpdate方法或insertOrUpdateBatch方法

实现MyBatisPlus自定义sql注入器的更多相关文章

  1. Mybatis-Plus如何自定义SQL注入器?

    有关Mybatis-Plus常用功能之前有做过一篇总结: MyBatisPlus常用功能总结!(附项目示例) 一.什么是SQL注入器 我们在使用Mybatis-Plus时,dao层都会去继承BaseM ...

  2. mybatis-plus 自定义SQL,XML形式,传参的几种方式

    mybatis-plus 自定义SQL,XML形式,传参的几种方式 前提说明 所涉及文件 传参类型说明 1.Java代码中使用QueryWrapper动态拼装SQL 2.简单类型参数(如String, ...

  3. SpringBoot集成MyBatis-Plus自定义SQL

    1.说明 本文介绍Spring Boot集成MyBatis-Plus框架后, 基于已经创建好的Spring Boot工程, 添加自定义的SQL实现复杂查询等操作. 自定义SQL主要有两种方式, 一种是 ...

  4. 小书MybatisPlus第3篇-自定义SQL

    本文档为一个系列,前面章节: 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查 小书MybatisPlus第2篇-条件构造器的应用及总结 书接上回,虽然Mybatis Plu ...

  5. spring boot集成mybatis-plus插件进行自定义sql方法开发时报nested exception is org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):

    spring boot集成mybatis-plus插件进行自定义sql方法开发时报nested exception is org.apache.ibatis.binding.BindingExcept ...

  6. phpcmsv9自定义sql语句查询模型实现

    在phpcmsv9中,自定义sql语句查询可不太好实现,传入sql语句查询很容易被内部转入生成一系列莫名其妙的sql语句,比如最佳前缀等等,直接造成sql语句查询错误,在此也提供两种解决办法,1修改底 ...

  7. thinkjs中自定义sql语句

    一直以为在使用thinkjs时,只能是它自带的sql语句查询,当遇到类似于这样的sql语句时,却不知道这该怎样来写程序,殊不知原来thinkjs可以执行自定义sql语句 SELECT * from a ...

  8. 11月16日《奥威Power-BI基于SQL的存储过程及自定义SQL脚本制作报表》腾讯课堂开课啦

           上周的课程<奥威Power-BI vs微软Power BI>带同学们全面认识了两个Power-BI的使用情况,同学们已经迫不及待想知道这周的学习内容了吧!这周的课程关键词—— ...

  9. django不定义model,直接执行自定义SQL

    如果不想定义model,直接执行自定义SQL,可如下操作: 1. 通过 connections获取db连接,如果是多个数据库,connections['dbName'] 来选择 2. 获取游标 cur ...

  10. Python Django 之 直接执行自定义SQL语句(二)

    转载自:https://my.oschina.net/liuyuantao/blog/712189 一般来说,最好用 Django 自带的模型来实现这些操作.这里仅仅只是为了学习使用原始 SQL 而做 ...

随机推荐

  1. 【JMeter】JMeter添加插件

    JMeter添加插件 目录 JMeter添加插件 一.前言 二.插件管理器 三.推荐插件 1.Custom Thread Groups (1)Ultmate Thread Group (2)Stepp ...

  2. vim 配色调整

    ~/.vimrc " Configuration file for vim set modelines=0 " CVE-2007-2438 set number " se ...

  3. 应用性能监控工具(pinpoint)部署

    Pinpoint是一款全链路分析工具,提供了无侵入式的调用链监控.方法执行详情查看.应用状态信息监控等功能.pinpoint使用HBASE储存数据. 下面介绍pinpoint部署及应用. 1.  安装 ...

  4. 使用redis pipeline提升性能

    前言 本篇来介绍一下redis pipeline,主要是由于最近一次在帮开发同学review代码的时候,发现对redis有个循环操作可以优化.场景大概是这样的,根据某个uid要从redis查询一批数据 ...

  5. SpringMVC配置web.xml文件详解(列举常用的配置)

    常用的web.xml的配置 1.Spring 框架解决字符串编码问题:过滤器 CharacterEncodingFilter(filter-name) 2.在web.xml配置监听器ContextLo ...

  6. 03.前后端分离中台框架 zhontai 项目代码生成器的使用

    zhontai 项目 基于 .Net7.x + Vue 等技术的前后端分离后台权限管理系统,想你所想的开发理念,希望减少工作量,帮助大家实现快速开发 后端地址:https://github.com/z ...

  7. Java将MySQL建表语句转换为SQLite的建表语句

    Java将MySQL建表语句转换为SQLite的建表语句 源代码: package com.fxsen.platform.core.util; import java.util.HashMap; im ...

  8. 《Web安全基础》02. 信息收集

    @ 目录 1:CDN 绕过 1.1:判断是否有 CDN 服务 1.2:常见绕过方法 1.3:相关资源 2:网站架构 3:WAF 4:APP 及其他资产 5:资产监控 本系列侧重方法论,各工具只是实现目 ...

  9. 搭建 QT6+OpenCv4.7+CMake的环境

    本文主要介绍如何搭建QT6+OpenCv的开发环境,基本流程如下 先安装CMake3.27.3,用来编译适用用QT的OpenCv的源码,安装完成后要配置系统的环境变量 安装Qt6的开发环境,并配置环境 ...

  10. 【火坑】一切从TimeSpan说起

    小编在编写WPF程序时,需要做一个判断:定时使用Modbus协议使用Quartz.net 定时任务读取设备中的数据,同时也使用定时任务判断是否长时间获取不到数据的情况,如果程序中超过一分钟没有获取到数 ...