java后端对代码创建的动态表进行DML操作(插入、更新、删除、修改)的实现示例


前言

项目上有个需求,需要根据业务类型,动态配置表单信息,根据配置完成的表单字段信息,动态创建与表单对应的业务数据表。然后将表单信息通过流程下发到具体的使用者用户,使用者用户根据业务类型配置的表单,填报表单数据,并提交业务数据到动态表单绑定的动态数据表中。数据提交完成后,要支持对已提交的数据进行修改、查询、删除,同时数据提交要支持批量插入已方便数据导入。
整个需求,动态数据表的创建由其他人实现,论到我这儿就涉及到对表的数据的操作,因此要支持对通过代码创建的持久化业务表的数据的增加、修改、删除、查询操作,技术难度没有,关键点主要是自定义SQL的构建和SQL的执行两个,自定义SQL如果采用纯手工拼接太过杂乱而且容易出错。在实现过程中,采用了如下两个组件:

详细实现过程如下所见。


一、动态SQL格式化器-DynamicSqlFormater

1. 功能介绍

动态SQL格式化器,是所有动态SQL格式化的规范定义,因此该类采用接口。定义了两个方法:

  • 通用的动态表的记录行单行格式化方法
  • 通用的动态表的记录行多行批量格式化方法

多行记录批量格式化方法提供了一个默认实现,该实现内直接抛出了一个不支持的异常,提供给子类重写实现。依据项目需求情况,目前的示例中,仅提供了INSERT的批量格式化功能。

2. 源码示例

package com.nbcio.modules.flowable.jgpt.dynamic;

import org.apache.ibatis.mapping.SqlCommandType;

import java.util.List;
import java.util.Map;

/**
 * @Description
 * @Author misterbig
 * @Date 2024/1/24
 */
public interface DynamicSqlFormater {
   

    /**
     * <h3>根据SqlCommandType格式化sql</h3>
     * <strong>支持的格式化类型为</strong>
     * <ul>
     *     <li>{@linkplain SqlCommandType#INSERT},支持批量格式化</li>
     *     <li>{@linkplain SqlCommandType#UPDATE}</li>
     *     <li>{@linkplain SqlCommandType#DELETE}</li>
     *     <li>{@linkplain SqlCommandType#SELECT}</li>
     * </ul>
     *
     * @param dynamicObject {@literal 字段-数据映射}
     * @param dynamicField  {@literal 字段-类型映射}
     * @param table         {@literal 动态表名称}
     * @return
     * @see SqlCommandType
     */
    String format(Map<String, Object> dynamicObject, Map<String, Object> dynamicField, String table);

    /**
     * <h3>根据SqlCommandType批量格式化sql</h3>
     * <strong>多个数据对象的格式化: 目前仅支持{@linkplain ClassifySqlFormater#INSERT}</strong>
     *
     * @param dynamicObjects {@literal 字段-数据映射集合}
     * @param dynamicField   {@literal 字段-类型映射}
     * @param table          {@literal 动态表名称}
     * @return
     */
    default String format(List<Map<String, Object>> dynamicObjects, Map<String, Object> dynamicField, String table) {
   
        throw new UnsupportedOperationException("格式化多个数据对象的SQL目前仅有批量插入支持, 当前实例如需支持需要自行实现格式化逻辑");
    }

}


二、动态表字段类型支持器-DynamicFieldSupporter

1. 功能介绍

动态表字段类型支持器,定义了项目要求的三种支持类型(VARCHAR、DATETIME、NUMBER),同时设置了一个其他类型(OTHER)用以提供默认处理。项目采用MYSQL数据库,VARCHAR和DATETIME类型在SQL格式化的时候,可以直接转换为字符串进行写入,只有NUMBER需要单独处理。其他类型,默认按照字符串进行处理。该支持器提供了两个方法:

  • 根据字段的类型值查找对应的支持类型,未找到对应类型时候,返回默认类型(OTHER)。
  • 根据提交的字段-类型映射关系数据,验证所有字段类型是否能够支持,不支持直接抛出异常并提示。

2. 源码示例

package com.nbcio.modules.flowable.jgpt.dynamic;

import java.util.Arrays;
import java.util.Map;

/**
 * @Description
 * @Author misterbig
 * @Date 2024/1/26
 */
public enum DynamicFieldSupporter {
   

    VARCHAR("1"),
    DATETIME("2"),
    NUMBER("3"),
    OTHER("0");

    public final String key;

    DynamicFieldSupporter(String key) {
   
        this.key = key;
    }

    /**
     * 检查动态表字段类型处理器是否支持
     *
     * @param fieldType
     * @throws UnsupportedOperationException
     */
    public static DynamicFieldSupporter getFieldType(String fieldType) {
   
        return Arrays.stream(DynamicFieldSupporter.values())
                .filter(supporter -> supporter.name().equalsIgnoreCase(fieldType) || supporter.key.equals(fieldType))
                .findAny()
                .orElse(OTHER);
    }

    /**
     * 检查动态表字段类型处理器是否支持
     *
     * @param fields
     * @throws UnsupportedOperationException
     */
    public static void checkFieldSupported(Map<String, Object> fields) {
   
        for (Map.Entry<String, Object> field : fields.entrySet()) {
   
            boolean isSupported = false;
            String fieldType = String.valueOf(field.getValue());
            for (DynamicFieldSupporter supporter : values()) {
   
                if (supporter.name().equalsIgnoreCase(fieldType) || supporter.key.equals(fieldType)) {
   
                    isSupported = true;
                }
            }
            if (!isSupported) {
   
                throw new UnsupportedOperationException(
                        String.format("当前字段类型格式化器暂不支持, 字段名称: {}, 字段类型: {}", field.getKey(), field.getValue()));
            }
        }
    }
}


三、分类SQL格式化器-ClassifySqlFormater

1. 功能介绍

针对项目要求支持的对动态

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mister-big

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值