|
|
|
|
package com.project.base.config;
|
|
|
|
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
|
|
|
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
|
|
|
|
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
|
|
|
|
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
|
|
|
|
|
import org.apache.ibatis.mapping.MappedStatement;
|
|
|
|
|
import org.apache.ibatis.mapping.SqlSource;
|
|
|
|
|
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 自定义选装件:MySQL 批量 Upsert
|
|
|
|
|
*/
|
|
|
|
|
public class InsertBatchOnDuplicateKeyUpdate extends AbstractMethod {
|
|
|
|
|
|
|
|
|
|
protected InsertBatchOnDuplicateKeyUpdate() {
|
|
|
|
|
super("batchUpsert"); // 方法名
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
|
|
|
|
|
final String methodName = "batchUpsert";
|
|
|
|
|
|
|
|
|
|
// 1. 准备 INSERT 字段
|
|
|
|
|
String columnScript = "(" + tableInfo.getKeyColumn() + "," +
|
|
|
|
|
tableInfo.getFieldList().stream()
|
|
|
|
|
.map(TableFieldInfo::getColumn)
|
|
|
|
|
.collect(Collectors.joining(",")) + ")";
|
|
|
|
|
|
|
|
|
|
// 2. 准备 VALUES 部分 (处理逻辑删除位)
|
|
|
|
|
String valuesScript = "(#{item." + tableInfo.getKeyProperty() + "}," +
|
|
|
|
|
tableInfo.getFieldList().stream()
|
|
|
|
|
.map(i -> {
|
|
|
|
|
// A. 如果是逻辑删除字段:处理“没传就默认 0”
|
|
|
|
|
if (i.isLogicDelete()) {
|
|
|
|
|
// 使用 IFNULL 保证如果 Java 对象里 deleted 是 null,数据库填入 0
|
|
|
|
|
return "IFNULL(#{item." + i.getProperty() + "}, 0)";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// B. 处理 TypeHandler (如之前处理的 JSON 字段)
|
|
|
|
|
if (i.getTypeHandler() != null) {
|
|
|
|
|
return "#{item." + i.getProperty() + ",typeHandler=" + i.getTypeHandler().getName() + "}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// C. 普通字段
|
|
|
|
|
return "#{item." + i.getProperty() + "}";
|
|
|
|
|
})
|
|
|
|
|
.collect(Collectors.joining(",")) + ")";
|
|
|
|
|
|
|
|
|
|
// 3. 准备 ON DUPLICATE KEY UPDATE 部分
|
|
|
|
|
String updateScript = tableInfo.getFieldList().stream()
|
|
|
|
|
// 排除主键和创建时间
|
|
|
|
|
.filter(i -> !i.getColumn().equals("create_time"))
|
|
|
|
|
.map(i -> {
|
|
|
|
|
// 如果是逻辑删除位,在更新时强制置为 0(即复活数据)
|
|
|
|
|
// 理由:全量同步中,只要数据还在钉钉列表里,就说明该部门/人员是活跃的
|
|
|
|
|
if (i.isLogicDelete()) {
|
|
|
|
|
return i.getColumn() + " = 0";
|
|
|
|
|
}
|
|
|
|
|
// 其他字段正常更新
|
|
|
|
|
return i.getColumn() + " = VALUES(" + i.getColumn() + ")";
|
|
|
|
|
})
|
|
|
|
|
.collect(Collectors.joining(",")) + ", update_time = NOW()";
|
|
|
|
|
|
|
|
|
|
String sql = String.format("<script>INSERT INTO %s %s VALUES <foreach collection=\"list\" item=\"item\" separator=\",\">%s</foreach> ON DUPLICATE KEY UPDATE %s</script>",
|
|
|
|
|
tableInfo.getTableName(), columnScript, valuesScript, updateScript);
|
|
|
|
|
|
|
|
|
|
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
|
|
|
|
|
return this.addInsertMappedStatement(mapperClass, modelClass, methodName, sqlSource, new NoKeyGenerator(), null, null);
|
|
|
|
|
}
|
|
|
|
|
}
|