You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
3.4 KiB

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);
}
}