在实际业务开发中,为了减少代码量,实现万变不离其宗的思想,像批量插入、查询、删除等数据库操作以动态参数的方式实现,本文将阐述动态参数实现mybatis批量插入核心代码

1.mapper文件写法

    <sql id="values">
        <foreach item="item" collection="list" separator=",">
            <foreach collection="item" item="detailItem" index="index" open="("
                     close=")" separator=",">
                #{detailItem}
            </foreach>
        </foreach>
    </sql>
    <!-- 批量新增单位信息表信息 -->
    <insert id="addSalAgencys" parameterType="list">
        INSERT INTO ${tableName} (
        <foreach collection="columns" item="columnItem" separator=",">
            ${columnItem}
        </foreach>)
         VALUES
        <include refid="values"></include>
    </insert>

2.持久化层函数

    /**
     * basic sql
     * @param tableName 表名
     * @param columns 列字段集合
     * @param list 值集合
     */
    void addSalAgencys(@Param("tableName") String tableName,
                       @Param("columns") List<String> columns,
                       @Param("list") List<List<Object>> list);

3.参数tableName是表名,这个没什么特别注意的,通过配置表的方式或者别的方式传入都可以,和数据库表名对应即可

columns列字段集合,直接用工具类ReflectionUtil获取就可以,工具类代码

import com.boss.bis.common.exception.BusinessException;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class ReflectionUtil {
    public static final char UNDERLINE = '_';
    private static final Logger log = LoggerFactory.getLogger(ReflectionUtil.class);

    public static List<Field> getFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        fieldList.addAll(Lists.newArrayList(clazz.getDeclaredFields()));
        if (!(clazz.getSuperclass().isAssignableFrom(Object.class))) {
            fieldList.addAll(getFields(clazz.getSuperclass()));
        }
        return fieldList;
    }

    public static Field getField(String fieldName, Class<?> cls) {
        try {
            return cls.getDeclaredField(underlineToCamel(fieldName));
        } catch (NoSuchFieldException e) {
            Class<?> parentCls = cls.getSuperclass();
            if (ObjectUtils.isEmpty(parentCls)) {
                log.error(e.getMessage(), e);
                throw new BusinessException(e.getMessage());
            }
            return getField(fieldName, parentCls);
        }
    }

    public static void setValueByField(String fieldName, Object object, Object value) {
        Field field;
        try{
            field = getField(fieldName, object.getClass());
            field.setAccessible(true);
        }catch (Exception e){
            log.error("字段不存在", e);
            return;
        }

        try {
            if (BigDecimal.class.equals(field.getType())) {
                field.set(object, new BigDecimal(String.valueOf(value)));
            } else if (String.class.equals(field.getType())) {
                field.set(object, value);
            }
        } catch (IllegalAccessException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(e.getMessage());
        }
    }

    /**
     * 下划线格式字符串转换为驼峰格式字符串
     *
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        if (param.indexOf(UNDERLINE) < 0) {
            return param;
        }
        String paramTmp = param.toLowerCase();
        int len = paramTmp.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = paramTmp.charAt(i);
            if (c == UNDERLINE) {
                if (++i < len) {
                    sb.append(Character.toUpperCase(paramTmp.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static Object getValueByField(String fieldName, Object object) {
        Field field;
        try{
            field = getField(fieldName, object.getClass());
            field.setAccessible(true);
        }catch (Exception e){
            log.error("字段不存在", e);
            throw new BusinessException(e.getMessage());
        }
        try {
            if (BigDecimal.class.equals(field.getType())) {
                return new BigDecimal(String.valueOf(field.get(object)));
            }
            return field.get(object);
        } catch (IllegalAccessException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(e.getMessage());
        }
    }
}

通过ReflectionUtil.getFields获取实体类的映射字段

// 数据库字段生成
        List<Field> fields = ReflectionUtil.getFields(cls);
        List<String> underList = new ArrayList<>();
        List<String> camelList = new ArrayList<>();
        StringBuilder colsql = new StringBuilder(200);
        for (Field field : fields) {
            if(Modifier.isStatic(field.getModifiers())){
                continue;
            }
            String name = field.getName();
            String underName = BisBeanUtils.camelToUnderline(name).toUpperCase();
            if(camelList.indexOf(name) > -1){
                continue;
            }
            underList.add(underName);
            camelList.add(name);
            colsql.append(underName + " as " + name).append(", ");
        }
        colsql.delete(colsql.length() - 2, colsql.length() - 1);

这样就获取到了带下划线的字段集合underList,即columns
camelList驼峰法的字段集合,用于第4点组装值集合
colsql查询字段并起驼峰法别名,类似于stu_name as stuName, stu_age as stuAge

这样查询出来的数据用map接收,得出来的map就会是以下这样,maps
在这里插入图片描述
4.组装插入的值集合list

private List<List<Object>> buildSaveData(List<Map> maps, List<String> camelList) {
        List<List<Object>> dataList = maps.stream().map(t -> {
            List<Object> list = new ArrayList<>();
            camelList.stream().forEach(field -> {
                list.add(t.get(field));
            });
            return list;
        }).collect(Collectors.toList());
        return dataList;
    }

以上就是mybatis实现动态参数批量插入的核心代码,描述上可能比较欠缺,毕竟是一只不太会表达的程序猿,有不明白的铁子可以给我留言。
在这里插入图片描述

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐