实现MyBatisPlus自定义sql注入器
目标:新增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注入器的更多相关文章
- Mybatis-Plus如何自定义SQL注入器?
有关Mybatis-Plus常用功能之前有做过一篇总结: MyBatisPlus常用功能总结!(附项目示例) 一.什么是SQL注入器 我们在使用Mybatis-Plus时,dao层都会去继承BaseM ...
- mybatis-plus 自定义SQL,XML形式,传参的几种方式
mybatis-plus 自定义SQL,XML形式,传参的几种方式 前提说明 所涉及文件 传参类型说明 1.Java代码中使用QueryWrapper动态拼装SQL 2.简单类型参数(如String, ...
- SpringBoot集成MyBatis-Plus自定义SQL
1.说明 本文介绍Spring Boot集成MyBatis-Plus框架后, 基于已经创建好的Spring Boot工程, 添加自定义的SQL实现复杂查询等操作. 自定义SQL主要有两种方式, 一种是 ...
- 小书MybatisPlus第3篇-自定义SQL
本文档为一个系列,前面章节: 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查 小书MybatisPlus第2篇-条件构造器的应用及总结 书接上回,虽然Mybatis Plu ...
- 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 ...
- phpcmsv9自定义sql语句查询模型实现
在phpcmsv9中,自定义sql语句查询可不太好实现,传入sql语句查询很容易被内部转入生成一系列莫名其妙的sql语句,比如最佳前缀等等,直接造成sql语句查询错误,在此也提供两种解决办法,1修改底 ...
- thinkjs中自定义sql语句
一直以为在使用thinkjs时,只能是它自带的sql语句查询,当遇到类似于这样的sql语句时,却不知道这该怎样来写程序,殊不知原来thinkjs可以执行自定义sql语句 SELECT * from a ...
- 11月16日《奥威Power-BI基于SQL的存储过程及自定义SQL脚本制作报表》腾讯课堂开课啦
上周的课程<奥威Power-BI vs微软Power BI>带同学们全面认识了两个Power-BI的使用情况,同学们已经迫不及待想知道这周的学习内容了吧!这周的课程关键词—— ...
- django不定义model,直接执行自定义SQL
如果不想定义model,直接执行自定义SQL,可如下操作: 1. 通过 connections获取db连接,如果是多个数据库,connections['dbName'] 来选择 2. 获取游标 cur ...
- Python Django 之 直接执行自定义SQL语句(二)
转载自:https://my.oschina.net/liuyuantao/blog/712189 一般来说,最好用 Django 自带的模型来实现这些操作.这里仅仅只是为了学习使用原始 SQL 而做 ...
随机推荐
- Java List集合根据某字段去重
去重方法 单个字段为条件去重 /** * 单字段去重 * @param jackpotList1 新集合 * @param jackpotList 需要去重的集合 * @return */ priva ...
- Java计算日期之间相差时间和解决浮点类型精度过长
计算日期之间相差 此处相差计算以分钟为单位,自行可根据业务场景更改 /** * 测试时间相差分钟 */ @Test public void getTime() { SimpleDateFormat s ...
- 如何新建一个django项目
1.新建项目 2选择django 3.接下来我们进入 djangotest目录输入以下命令,启动服务器: python manage.py runserver 0.0.0.0:8000 0.0.0.0 ...
- 获取Rtx用户状态方法
背景:企业OA系统需要与Rtx集成,且高权限身份用户需要获取符合某一条下的所有员工rtx状态... 方案:以此背景,基于rtx sdk做二次开发, 1.后台调用RootObj.QueryUserSta ...
- WEB前端资源网站推荐
https://www.bootcss.com/ https://www.bootcdn.cn/ http://www.jeasyui.net/plugins/756.html
- mysql-workbench-community报错解决办法
输入以下命令: sudo apt-get -f install 参考链接:https://www.jianshu.com/p/767c9a29b403
- linux下的venv使用
首先安装该模块: sudo apt-get install python3-venv 之后创建用于存储工程的文件夹 mkdir [filename] 创建环境: python3 -m venv ven ...
- 王道oj/problem18
网址:略 思路:见注释:有bug:插入时1和2的结果正好相反,稍后编辑. 代码: #define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#incl ...
- spring-mvc 系列:视图(ThymeleafView、InternalResourceView、RedirectView)
目录 一.ThymeleafView 二.转发视图 三.重定向视图 四.视图控制器view-controller 五.配置jsp解析 SpringMVC中的视图是View接口,视图的作用渲染数据,将模 ...
- Mybatis框架的搭建和基本使用
本文总结最原始Mybatis框架的搭建和最基本使用(不涉及Spring框架体系). 1 依赖 首先,我们要引入Mybatis依赖: <dependency> <groupId> ...