✨ 添加 mybatis-plus-mysql 扩展, 自定义了一些全局方法,目前只适用MySQL,提供了自定义扩展 mybatis-plus模块的示例
This commit is contained in:
26
ballcat-extends/mybatis-plus-mysql-extend/pom.xml
Normal file
26
ballcat-extends/mybatis-plus-mysql-extend/pom.xml
Normal 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>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user