目标:新增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. Linux内核笔记(三)内核编程语言和环境

    学习概要: Linux内核使用的编程语言.目标文件格式.编译环境.内联汇编.语句表达式.寄存器变量.内联函数 c和汇编函数之间的相互调用机制Makefile文件的使用方法. as86汇编语言语法 汇编 ...

  2. vulnhub_me and my grilfriend

    解题步骤 主机nmap扫描,开放22和80端口 访问该ip,发现只能本地访问 查看源代码,提示需要使用x-forwarded-for的请求头,可以在burp suite中每次添加一个请求头,也可以使用 ...

  3. centos7升级内核到最新稳定版

    前言 centos7默认的内核版本才3.10,诸如VXLAN.eBPF等特性无法体验,因此需要升级.目前(2022.02)Linux的内核版本已更新到5.16. 步骤 更新仓库 yum update ...

  4. 一文理解GIT的代码冲突

    对于GIT,不知道有没有人和我一样,很长时间都是小心翼翼.紧张兮兮,生怕一不小心,自己辛苦写的代码没了. 特别是代码冲突,更是难到我无法理解,每次都要求助于百度,跟着人家的教程一步步解决,下一次还是这 ...

  5. Web通用漏洞--CSRF

    Web通用漏洞--CSRF 漏洞简介 CSRF(Cross Site Request Forgery, 跨站请求伪造/客户端请求伪造),即通过伪造访问数据包并制作成网页的形式,使受害者访问伪造网页,同 ...

  6. LabVIEW图形化TensoRT工具包的安装下载分享

    前言 Hello,大家好,我是virobotics(仪酷智能)今天我们一起来看一下如何安装[LabVIEWTensoRT工具包]. 一.LabVIEW图形化TensoRT工具包简介 工具包特点: 图形 ...

  7. 《高级程序员 面试攻略 》RabbitMQ 如何实现可靠性

    RabbitMQ 提供了多种机制来实现消息传递的可靠性.下面是一些常见的方法: 1. 持久化消息:RabbitMQ 允许将消息标记为持久化,以确保即使在发生故障或重启后,消息也不会丢失.通过将消息的` ...

  8. 【pandas小技巧】--DataFrame的显示参数

    我们在jupyter notebook中使用pandas显示DataFrame的数据时,由于屏幕大小,或者数据量大小的原因,常常会觉得显示出来的表格不是特别符合预期. 这时,就需要调整pandas显示 ...

  9. pytest-xdist分布式测试原理浅析

    pytest-xdist执行流程: 解析命令行参数:pytest-xdist 会解析命令行参数,获取用户指定的分发模式.进程数.主机列表等信息. 加载测试用例:pytest-xdist 会加载所有的 ...

  10. C盘无法创建文件处理

    icacls c:\ /setintegritylevel M 打开终端执行上方命令,亲测可用