目的
通过数据库名、表名实现动态添加活更新数据。添加或更新由唯一索引判断。
实现
思路
查询数据库表的唯一索引-CSDN博客
根据数据库表名动态查询表字段-CSDN博客
达梦数据库根据唯一索引批量新增或更新数据-CSDN博客
将数据转换为sql语句需要的格式
完善代码,实现功能
实现代码
将数据转换为sql语句需要的格式
/*** 将数据转换为sql语句需要的格式** @param tableName 表名* @param dataList 接受到的数据* @param uniqueIndex 索引列* @param <T> 泛型类* @return 转换后的数据*/public static <T> Map<String, Object> cvtDataTypeByTable2(String tableName, List<T> dataList, List<String> uniqueIndex) {//根据表名查询字段列表Map<String, List<String>> columnsByTable = QueryColumnsByTableName.queryColumnsByTableName(tableName);//创建存储返回信息的retMapMap<String, Object> retMap = new LinkedHashMap<>();//获取所有的表字段List<String> columns = columnsByTable.get(tableName);//获取需要更新的字段,即索引字段外的其它所有字段List<String> updateColumns = columns.stream().filter(column -> !uniqueIndex.contains(column)).collect(Collectors.toList());//处理传入的数据List<List<Map<String, Object>>> columnsValueList = dataList.stream().map(data -> {List<Map<String, Object>> singleColumnValue = columns.stream()//对数据列表进行流式处理.map(column -> { // 对每个列进行映射操作try {//将列名转换为驼峰式或小写String columnName = Convert2CamelCaseOrLowerCase.convertToCamelCaseOrLowerCase(column);//根据列名获取数据对象的值Object columnValue = getValueByFieldName(data, columnName);return new LinkedHashMap<String, Object>() {{//将列名作为键,列名作为值放入Map中put("name", column);// 将列值作为键,列值作为值放入Map中put("value", columnValue);}};} catch (NoSuchFieldException | IllegalAccessException e) {// 处理异常,例如记录日志或抛出更具体的异常e.printStackTrace();return null; // 或者抛出异常}}).collect(Collectors.toList());//将映射结果收集为Listreturn singleColumnValue; //返回单个列的值列表}).collect(Collectors.toList());//将映射结果收集为ListretMap.put("columns", columns);retMap.put("uniqueIndex", uniqueIndex);retMap.put("data", columnsValueList);retMap.put("updateColumns", updateColumns);return retMap;}
service层代码
package org.springblade.modules.system.service;import org.apache.poi.ss.formula.functions.T;import java.util.List;public interface I类名{/*** 更新或新增第三方传入数据** @param dataName 数据库名* @param tableName 表名* @param dataList 传入数据* @return 是否成功*/<T> boolean updateOrSaveDsfData(String dataName, String tableName, List<T> dataList);}
serevice实现类代码
package org.springblade.modules.system.service.impl;import lombok.extern.slf4j.Slf4j;
import org.springblade.modules.system.helper.CvtDataTypeByTable;
import org.springblade.modules.system.mapper.DataBodyMapper;
import org.springblade.modules.system.service.IDsfSjCcService;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;
import java.util.Map;/*** 存储第三方传入信息 实现类*/
@Service
@Slf4j
public class 类名 implements I类名 {@Resourceprivate DataBodyMapper dataBodyMapper;@Overridepublic <T> boolean updateOrSaveDsfData(String dataName, String tableName, List<T> dataList) {if (dataList == null || dataList.isEmpty()) {// 返回 false,并且不抛出异常,而是将异常处理交给调用者return false;}try {// 查询唯一索引List<String> unique = dataBodyMapper.selectUniqueIndex_DM(dataName, tableName);List<String> uniqueIndex = new ArrayList<>();if (unique != null && !unique.isEmpty()) {for (String row : unique) {uniqueIndex.addAll(Arrays.asList(row.split(",")));}}//将收到的数据转为存储所需格式Map<String, Object> formattedDataMap = CvtDataTypeByTable.cvtDataTypeByTable2(tableName, dataList, uniqueIndex);//从Map中获取正确的类型,避免强制类型转换List<Object> data = (List<Object>) formattedDataMap.get("data");List<String> uniqueIndexList = (List<String>) formattedDataMap.get("uniqueIndex");List<String> columns = (List<String>) formattedDataMap.get("columns");List<String> updateColumns = (List<String>) formattedDataMap.get("updateColumns");// 执行批量插入或更新操作dataBodyMapper.batchInsertOrUpdate(tableName, data, uniqueIndexList, columns, updateColumns);} catch (Exception e) {// 可以考虑记录日志而不是打印堆栈跟踪e.printStackTrace();return false;}return true;}}
mapper层代码
package org.springblade.modules.system.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.modules.system.entity.DataBodyEntity;import java.util.List;/*** 数据主体 Mapper 接口** @author BladeX* @since 2022-12-12*/
public interface DataBodyMapper extends BaseMapper<DataBodyEntity> {/*** 插入或更新** @param tableName 表名* @param dataList 表数据* @param uniqueIndex 索引字段* @param columns 表字段* @param updateColumns 更新字段*/// @InterceptorIgnore(tenantLine = "true")void batchInsertOrUpdate(String tableName, List<Object> dataList, List<String> uniqueIndex, List<String> columns, List<String> updateColumns);
}
mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.modules.system.mapper.DataBodyMapper"><insert id="batchInsertOrUpdate" parameterType="java.util.List">MERGE INTO ${tableName} dstUSING(<foreach collection="dataList" item="data" open="(" separator=" UNION ALL " close=")">SELECT<foreach collection="data" item="dt" separator=",">#{dt.value} AS ${dt.name}</foreach>FROM dual</foreach>)srcON<foreach collection="uniqueIndex" item="unique_index_column" open="(" separator=" and" close=")">dst.${unique_index_column} = src.${unique_index_column}</foreach>WHEN MATCHED THENUPDATE SET<foreach collection="updateColumns" item="column" separator=",">dst.${column} = src.${column}</foreach>WHEN NOT MATCHED THENINSERT<foreach collection="columns" item="field" open="(" separator="," close=")">${field}</foreach>VALUES<foreach collection="columns" item="column" open="(" separator="," close=")">src.${column}</foreach></insert></mapper>