添加 mybatis-plus-mysql 扩展, 自定义了一些全局方法,目前只适用MySQL,提供了自定义扩展 mybatis-plus模块的示例

This commit is contained in:
b2baccline
2020-06-09 21:28:40 +08:00
parent ca54d7fbae
commit 929e12a090
8 changed files with 421 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ballcat-extends</artifactId>
<groupId>com.hccake</groupId>
<version>0.0.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mybatis-plus-mysql-extend</artifactId>
<dependencies>
<dependency>
<groupId>com.hccake</groupId>
<artifactId>mybatis-plus-extend</artifactId>
<version>0.0.2</version>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -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<T> extends com.baomidou.mybatisplus.core.mapper.BaseMapper<T> {
/**
* 批处理 如果重复则忽略
*
* @param list 值列表
* @return int
* @author lingting 2020-05-27 11:41:28
*/
int insertIgnoreByBatch(@Param("list") List<T> 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<T> 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<T> 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<T> list, @Param("columns") Columns<T> columns);
}

View File

@@ -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<T> {
public static final String COLUMN_FLAG = "@";
/**
* 缓存 全类名 方法名 字段名
*/
private static final Map<String, ConcurrentHashMap<String, String>> COLUMN_CACHE_MAP = new ConcurrentHashMap<>();
/**
* 自定义字段
*/
private final List<Column> list = new ArrayList<>();
/**
* 类的所有字段
*/
private final List<String> back = new ArrayList<>();
/**
* 是否忽略设置的字段
*/
private boolean ignore = false;
private Columns() {
}
private Columns(SFunction<T, ?> sf) {
this(sf, null);
}
private Columns(SFunction<T, ?> sf, String val) {
this.add(sf, val);
}
public static <T> Columns<T> create() {
return new Columns<>();
}
public static <T> Columns<T> create(SFunction<T, ?> sf) {
return new Columns<>(sf);
}
public static <T> Columns<T> create(SFunction<T, ?> sf, String val) {
return new Columns<>(sf, val);
}
public Columns<T> add(SFunction<T, ?> sf) {
return add(sf, null);
}
/**
* @param val 自定义的替换sql {@link Columns#COLUMN_FLAG} 表示字段名
* @author lingting 2020-05-27 17:57:35
*/
public Columns<T> add(SFunction<T, ?> 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<T, ?> sf) {
SerializedLambda lambda = SerializedLambda.resolve(sf);
if (!COLUMN_CACHE_MAP.containsKey(lambda.getImplClass().getName())) {
ConcurrentHashMap<String, String> 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<T> ignore() {
this.ignore = true;
return this;
}
/**
* 设置不忽略设置的字段
*
* @author lingting 2020-05-28 11:05:59
*/
public Columns<T> set() {
this.ignore = false;
return this;
}
@Data
@Accessors(chain = true)
public static class Column {
private String name;
private String val;
}
}

View File

@@ -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<String> set) {
set.add("createTime");
}
@Override
public void pushMethods(List<AbstractMethod> list) {
list.add(new InsertIgnoreByBatch());
list.add(new InsertOrUpdateByBatch());
list.add(new InsertOrUpdateFieldByBatch());
}
}

View File

@@ -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("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
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("</foreach>");
return valueSql;
}
}

View File

@@ -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 "<script>insert ignore into %s %s values %s</script>";
}
@Override
protected String getId() {
return "insertIgnoreByBatch";
}
}

View File

@@ -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 "<script>insert into %s %s values %s</script>";
}
@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("<if test=\"!ignore\">").append(ignore).append("</if>");
return sql.toString();
}
}

View File

@@ -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 = "<script>insert into %s %s values %s</script>";
@Override
protected String getSql() {
return "<script>insert into %s %s values %s</script>";
}
@Override
protected String getId() {
return "insertOrUpdateFieldByBatch";
}
@Override
protected String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
StringBuilder sql = super.prepareValuesBuildSqlForMysqlBatch(tableInfo);
sql.append(" ON DUPLICATE KEY UPDATE ")
// 如果模式为 不忽略设置的字段
.append("<if test=\"!columns.ignore\">")
.append("<foreach collection=\"columns.list\" item=\"item\" index=\"index\" separator=\",\" >")
.append("${item.name}=${item.val}")
.append("</foreach>")
.append("</if>");
// 如果模式为 忽略设置的字段
sql.append("<if test=\"columns.ignore\">")
.append("<foreach collection=\"columns.back\" item=\"item\" index=\"index\" separator=\",\" >")
.append("${item}=VALUES(${item})")
.append("</foreach>")
.append("</if>");
return sql.toString();
}
}