From 929e12a0908d50961229baa9591c54627cca51a1 Mon Sep 17 00:00:00 2001 From: b2baccline <23131013+b2baccline@users.noreply.github.com> Date: Tue, 9 Jun 2020 21:28:40 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=B7=BB=E5=8A=A0=20mybatis-plus-?= =?UTF-8?q?mysql=20=E6=89=A9=E5=B1=95,=20=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E4=BA=86=E4=B8=80=E4=BA=9B=E5=85=A8=E5=B1=80=E6=96=B9=E6=B3=95?= =?UTF-8?q?=EF=BC=8C=E7=9B=AE=E5=89=8D=E5=8F=AA=E9=80=82=E7=94=A8MySQL,?= =?UTF-8?q?=E6=8F=90=E4=BE=9B=E4=BA=86=E8=87=AA=E5=AE=9A=E4=B9=89=E6=89=A9?= =?UTF-8?q?=E5=B1=95=20mybatis-plus=E6=A8=A1=E5=9D=97=E7=9A=84=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis-plus-mysql-extend/pom.xml | 26 ++++ .../extend/mybatis/plus/mysql/BaseMapper.java | 57 +++++++ .../extend/mybatis/plus/mysql/Columns.java | 142 ++++++++++++++++++ .../mybatis/plus/mysql/MybatisConfig.java | 30 ++++ .../plus/mysql/methods/BaseInsertBatch.java | 67 +++++++++ .../mysql/methods/InsertIgnoreByBatch.java | 16 ++ .../mysql/methods/InsertOrUpdateByBatch.java | 42 ++++++ .../methods/InsertOrUpdateFieldByBatch.java | 41 +++++ 8 files changed, 421 insertions(+) create mode 100644 ballcat-extends/mybatis-plus-mysql-extend/pom.xml create mode 100644 ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/BaseMapper.java create mode 100644 ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/Columns.java create mode 100644 ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/MybatisConfig.java create mode 100644 ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/BaseInsertBatch.java create mode 100644 ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertIgnoreByBatch.java create mode 100644 ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertOrUpdateByBatch.java create mode 100644 ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertOrUpdateFieldByBatch.java diff --git a/ballcat-extends/mybatis-plus-mysql-extend/pom.xml b/ballcat-extends/mybatis-plus-mysql-extend/pom.xml new file mode 100644 index 00000000..64b057fa --- /dev/null +++ b/ballcat-extends/mybatis-plus-mysql-extend/pom.xml @@ -0,0 +1,26 @@ + + + + ballcat-extends + com.hccake + 0.0.2 + + 4.0.0 + + mybatis-plus-mysql-extend + + + + com.hccake + mybatis-plus-extend + 0.0.2 + + + + cn.hutool + hutool-all + + + \ No newline at end of file diff --git a/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/BaseMapper.java b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/BaseMapper.java new file mode 100644 index 00000000..dcb91213 --- /dev/null +++ b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/BaseMapper.java @@ -0,0 +1,57 @@ +package com.hccake.extend.mybatis.plus.mysql; + +import com.hccake.extend.mybatis.plus.config.StaticConfig; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 所有的 Mapper接口 都需要继承当前接口 + * 如果想自己定义其他的全局方法, 您的全局 BaseMapper 需要继承当前接口 + * + * @author lingting 2020/5/27 11:39 + */ +public interface BaseMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 批处理 如果重复则忽略 + * + * @param list 值列表 + * @return int + * @author lingting 2020-05-27 11:41:28 + */ + int insertIgnoreByBatch(@Param("list") List list); + + /** + * 批处理 如果重复则更新 + * + * @param list 值列表 + * @param ignore 是否忽略全局配置的忽略字段 {@link StaticConfig#UPDATE_IGNORE_FIELDS} + * @return int + * @author lingting 2020-05-27 11:41:28 + */ + int insertOrUpdateByBatch(@Param("list") List list, @Param("ignore") boolean ignore); + + /** + * 批处理 如果重复则更新 直接调用本方法会 忽略全局配置的忽略字段 {@link StaticConfig#UPDATE_IGNORE_FIELDS} + * + * @param list 值列表 + * @return int + * @author lingting 2020-05-27 11:41:28 + */ + default int insertOrUpdateByBatch(@Param("list") List list) { + return insertOrUpdateByBatch(list, true); + } + + /** + * 自定义 如果重复 需要更新的 field + * 当传入的 columns.ignore 属性为 true时 + * 会使用您传入的 字段值 去覆盖 不在 columns.list 中 字段 的值 + * + * @param list 值列表 + * @param columns 字段 + * @return int + * @author lingting 2020-05-27 15:48:20 + */ + int insertOrUpdateFieldByBatch(@Param("list") List list, @Param("columns") Columns columns); +} \ No newline at end of file diff --git a/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/Columns.java b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/Columns.java new file mode 100644 index 00000000..e98afa34 --- /dev/null +++ b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/Columns.java @@ -0,0 +1,142 @@ +package com.hccake.extend.mybatis.plus.mysql; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda; +import lombok.Data; +import lombok.Getter; +import lombok.experimental.Accessors; +import org.apache.ibatis.reflection.property.PropertyNamer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 用于mybatis 自定义的 列 + * + * @author lingting 2020/5/27 15:53 + */ +@Getter +public class Columns { + public static final String COLUMN_FLAG = "@"; + /** + * 缓存 全类名 方法名 字段名 + */ + private static final Map> COLUMN_CACHE_MAP = new ConcurrentHashMap<>(); + /** + * 自定义字段 + */ + private final List list = new ArrayList<>(); + /** + * 类的所有字段 + */ + private final List back = new ArrayList<>(); + + /** + * 是否忽略设置的字段 + */ + private boolean ignore = false; + + private Columns() { + } + + private Columns(SFunction sf) { + this(sf, null); + } + + private Columns(SFunction sf, String val) { + this.add(sf, val); + } + + public static Columns create() { + return new Columns<>(); + } + + public static Columns create(SFunction sf) { + return new Columns<>(sf); + } + + public static Columns create(SFunction sf, String val) { + return new Columns<>(sf, val); + } + + public Columns add(SFunction sf) { + return add(sf, null); + } + + /** + * @param val 自定义的替换sql {@link Columns#COLUMN_FLAG} 表示字段名 + * @author lingting 2020-05-27 17:57:35 + */ + public Columns add(SFunction sf, String val) { + String column = getColumn(sf); + if (StrUtil.isEmpty(val)) { + val = "VALUES(" + column + ")"; + } + + list.add(new Column() + .setName(column) + .setVal(val.replaceAll(COLUMN_FLAG, column)) + ); + back.remove(column); + return this; + } + + /** + * 获取方法所代表的表的字段名 + * + * @author lingting 2020-05-27 17:56:40 + */ + public String getColumn(SFunction sf) { + SerializedLambda lambda = SerializedLambda.resolve(sf); + + if (!COLUMN_CACHE_MAP.containsKey(lambda.getImplClass().getName())) { + ConcurrentHashMap map = new ConcurrentHashMap<>(LambdaUtils.getColumnMap(lambda.getImplClass()).size()); + LambdaUtils.getColumnMap(lambda.getImplClass()).forEach((k, v) -> { + map.put(k, v.getColumn()); + }); + COLUMN_CACHE_MAP.put(lambda.getImplClass().getName(), map); + } + + // 设置全字段名 + if (back.size() == 0 && COLUMN_CACHE_MAP.get(lambda.getImplClass().getName()).size() != 0) { + COLUMN_CACHE_MAP.get(lambda.getImplClass().getName()).forEach((k, v) -> { + back.add(v); + }); + } + + return COLUMN_CACHE_MAP.get(lambda.getImplClass().getName()) + .get(LambdaUtils.formatKey(PropertyNamer.methodToProperty(lambda.getImplMethodName()))); + } + + /** + * 忽略设置的字段 + * + * @author lingting 2020-05-28 11:06:15 + */ + public Columns ignore() { + this.ignore = true; + return this; + } + + /** + * 设置不忽略设置的字段 + * + * @author lingting 2020-05-28 11:05:59 + */ + public Columns set() { + this.ignore = false; + return this; + } + + @Data + @Accessors(chain = true) + public static class Column { + private String name; + private String val; + } +} + diff --git a/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/MybatisConfig.java b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/MybatisConfig.java new file mode 100644 index 00000000..2fe90196 --- /dev/null +++ b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/MybatisConfig.java @@ -0,0 +1,30 @@ +package com.hccake.extend.mybatis.plus.mysql; + +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.hccake.extend.mybatis.plus.config.MybatisConfigurer; +import com.hccake.extend.mybatis.plus.mysql.methods.InsertIgnoreByBatch; +import com.hccake.extend.mybatis.plus.mysql.methods.InsertOrUpdateByBatch; +import com.hccake.extend.mybatis.plus.mysql.methods.InsertOrUpdateFieldByBatch; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.Set; + +/** + * @author lingting 2020/5/27 11:43 + */ +@Configuration +public class MybatisConfig implements MybatisConfigurer { + + @Override + public void pushIgnoreFields(Set set) { + set.add("createTime"); + } + + @Override + public void pushMethods(List list) { + list.add(new InsertIgnoreByBatch()); + list.add(new InsertOrUpdateByBatch()); + list.add(new InsertOrUpdateFieldByBatch()); + } +} diff --git a/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/BaseInsertBatch.java b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/BaseInsertBatch.java new file mode 100644 index 00000000..289e626f --- /dev/null +++ b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/BaseInsertBatch.java @@ -0,0 +1,67 @@ +package com.hccake.extend.mybatis.plus.mysql.methods; + +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import org.apache.ibatis.executor.keygen.NoKeyGenerator; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; + +/** + * 所有插入自定义方法的父类 + * + * @author lingting 2020/5/27 15:14 + */ +public abstract class BaseInsertBatch extends AbstractMethod { + + @Override + public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) { + SqlSource sqlSource = languageDriver.createSqlSource(configuration, + String.format(getSql(), tableInfo.getTableName(), + prepareFieldSql(tableInfo), + prepareValuesSqlForMysqlBatch(tableInfo) + ), + modelClass); + return this.addInsertMappedStatement(mapperClass, modelClass, getId(), sqlSource, new NoKeyGenerator(), null, null); + } + + protected String prepareFieldSql(TableInfo tableInfo) { + StringBuilder fieldSql = new StringBuilder(); + fieldSql.append(tableInfo.getKeyColumn()).append(","); + tableInfo.getFieldList().forEach(x -> fieldSql.append(x.getColumn()).append(",")); + fieldSql.delete(fieldSql.length() - 1, fieldSql.length()); + fieldSql.insert(0, "("); + fieldSql.append(")"); + return fieldSql.toString(); + } + + /** + * 获取注册的脚本 + * + * @return java.lang.String + * @author lingting 2020-06-09 20:38:54 + */ + abstract protected String getSql(); + + /** + * 获取脚本id 即 方法名 + * + * @return java.lang.String + * @author lingting 2020-06-09 20:39:30 + */ + abstract protected String getId(); + + + protected String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) { + return prepareValuesBuildSqlForMysqlBatch(tableInfo).toString(); + } + + protected StringBuilder prepareValuesBuildSqlForMysqlBatch(TableInfo tableInfo) { + final StringBuilder valueSql = new StringBuilder(); + valueSql.append(""); + valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},"); + tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},")); + valueSql.delete(valueSql.length() - 1, valueSql.length()); + valueSql.append(""); + return valueSql; + } +} diff --git a/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertIgnoreByBatch.java b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertIgnoreByBatch.java new file mode 100644 index 00000000..2a5c03ae --- /dev/null +++ b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertIgnoreByBatch.java @@ -0,0 +1,16 @@ +package com.hccake.extend.mybatis.plus.mysql.methods; + +/** + * @author lingting 2020/5/27 11:47 + */ +public class InsertIgnoreByBatch extends BaseInsertBatch { + @Override + protected String getSql() { + return ""; + } + + @Override + protected String getId() { + return "insertIgnoreByBatch"; + } +} diff --git a/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertOrUpdateByBatch.java b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertOrUpdateByBatch.java new file mode 100644 index 00000000..065ce6a1 --- /dev/null +++ b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertOrUpdateByBatch.java @@ -0,0 +1,42 @@ +package com.hccake.extend.mybatis.plus.mysql.methods; + +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.hccake.extend.mybatis.plus.config.StaticConfig; + +/** + * @author lingting 2020/5/27 11:47 + */ +public class InsertOrUpdateByBatch extends BaseInsertBatch { + @Override + protected String getSql() { + return ""; + } + + @Override + protected String getId() { + return "insertOrUpdateByBatch"; + } + + @Override + protected String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) { + StringBuilder sql = super.prepareValuesBuildSqlForMysqlBatch(tableInfo); + sql.append(" ON DUPLICATE KEY UPDATE "); + StringBuilder ignore = new StringBuilder(); + + tableInfo.getFieldList().forEach(field -> { + // 默认忽略字段 + if (!StaticConfig.UPDATE_IGNORE_FIELDS.contains(field.getProperty())) { + sql.append(field.getColumn()).append("=").append("VALUES(").append(field.getColumn()).append("),"); + } else { + ignore.append(",").append(field.getColumn()).append("=").append("VALUES(").append(field.getColumn()).append(")"); + } + }); + + // 删除最后一个多余的逗号 + sql.delete(sql.length() - 1, sql.length()); + + // 配置不忽略全局配置字段时的sql部分 + sql.append("").append(ignore).append(""); + return sql.toString(); + } +} diff --git a/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertOrUpdateFieldByBatch.java b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertOrUpdateFieldByBatch.java new file mode 100644 index 00000000..3cdc4893 --- /dev/null +++ b/ballcat-extends/mybatis-plus-mysql-extend/src/main/java/com/hccake/extend/mybatis/plus/mysql/methods/InsertOrUpdateFieldByBatch.java @@ -0,0 +1,41 @@ +package com.hccake.extend.mybatis.plus.mysql.methods; + +import com.baomidou.mybatisplus.core.metadata.TableInfo; + +/** + * @author lingting 2020/5/27 11:47 + */ +public class InsertOrUpdateFieldByBatch extends BaseInsertBatch { + private static final String SQL = ""; + + @Override + protected String getSql() { + return ""; + } + + @Override + protected String getId() { + return "insertOrUpdateFieldByBatch"; + } + + @Override + protected String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) { + StringBuilder sql = super.prepareValuesBuildSqlForMysqlBatch(tableInfo); + sql.append(" ON DUPLICATE KEY UPDATE ") + // 如果模式为 不忽略设置的字段 + .append("") + .append("") + .append("${item.name}=${item.val}") + .append("") + .append(""); + + // 如果模式为 忽略设置的字段 + sql.append("") + .append("") + .append("${item}=VALUES(${item})") + .append("") + .append(""); + return sql.toString(); + } + +}