根据JSON数据自动生成ClickHouse的Insert语句

如果你还不知道怎么建表请移步 根据JsonSchema生成阿里云ClickHouse建表语句

这里就直接贴代码了,建表的规则,字段规则都在上方链接

    private static final String SCHEMA_TYPE = "type";
    private static final String SCHEMA_TYPE_OBJECT = "object";
    private static final String SCHEMA_TYPE_ARRAY = "array";
    private static final String SCHEMA_TYPE_NULL = "null";
    private static final String SCHEMA_TYPE_INTEGER = "integer";
    private static final String SCHEMA_TYPE_NUMBER = "number";
    private static final String SCHEMA_PROPERTIES = "properties";
    private static final String SCHEMA_ITEMS = "items";
    private static final String SCHEMA_REQUIRED = "required";
    private static final Map<String, String> typeConversion = new HashMap<>(16);
    static {
        typeConversion.put("string", " String ");
        typeConversion.put("integer", " Int64 ");
        typeConversion.put("boolean", " String ");
        typeConversion.put("number", " Decimal64(8) ");
    }


    /**
     * 根据JSON数据生成clickHouse表的Insert语句
     *
     * 1、根据JSON的所有节点生成对应的节点Insert语句
     *
     * @param source 数据源
     * @param scene 数据源场景
     * @param json json数据
     * @param schema jsonSchema
     * @return SQL列表
     */
    public static List<String> json2InsertSql(String source, String scene, String json, String schema) {
        JSONObject schemaNode = JSON.parseObject(schema);
        String nodeType = schemaNode.getString(SCHEMA_TYPE);
        String rootTableName = source + "_" + scene;
        if (SCHEMA_TYPE_OBJECT.equals(nodeType)) {
            return mergeInsertSql(jsonObj2InsertSql(rootTableName, null, null, schemaNode.getJSONObject(SCHEMA_PROPERTIES), JSON.parseObject(json)));
        } else if (SCHEMA_TYPE_ARRAY.equals(nodeType)) {
            return mergeInsertSql(jsonArray2InsertSql(rootTableName, null, null, schemaNode.getJSONObject(SCHEMA_ITEMS), JSON.parseArray(json)));
        }
        throw new BusinessErrException("Unable to resolve JSONSchema!");
    }

    /**
     * 单挑插入的SQL组装为为批量插入
     * @param sqlList
     * @return
     */
    private static List<String> mergeInsertSql(List<String> sqlList) {
        List<String> result = new ArrayList<>();
        Map<String, List<String>> resultMap = new HashMap<>();
        sqlList.forEach(sql -> {
            String v = sql.substring(sql.indexOf("(", sql.indexOf(")")));
            String k = sql.substring(0, sql.indexOf("(", sql.indexOf(")")));
            List<String> values = resultMap.get(k);
            if (CollectionUtils.isEmpty(values)) {
                values = new ArrayList<>();
            }
            values.add(v);
            resultMap.put(k, values);
        });
        resultMap.forEach((filed, valueList) -> {
            StringBuilder sql = new StringBuilder(filed);
            valueList.forEach(value -> {
                sql.append(value.replace(";", ","));
            });
            String substring = sql.substring(0, sql.length() - 1);
            result.add(substring + ";");
        });
        return result;
    }


    /**
     * JSON对象数据生成 clickHouse的Insert语句
     * @param tableName 指定表名
     * @param parentIdName 父节点主键名
     * @param parentId 父节点主键ID
     * @param properties jsonSchema中的字段表
     * @param jsonData 数据
     * @return sql列表
     */
    private static List<String> jsonObj2InsertSql(String tableName, String parentIdName, String parentId, JSONObject properties, JSONObject jsonData) {
        if (properties == null) {
            return new ArrayList<>();
        }
        String tableKey = tableName + "_jzx_id";
        List<String> result = new ArrayList<>();
        String id = GuidUtils.random();
        Set<String> keySet = properties.keySet();
        for (String key : keySet) {
            JSONObject typeObj = properties.getJSONObject(key);
            String type = typeObj.getString(SCHEMA_TYPE);
            if (StringUtils.isEmpty(type)) {
                continue;
            }
            switch (type) {
                case SCHEMA_TYPE_OBJECT:
                    result.addAll(jsonObj2InsertSql(tableName + "_" + key, tableKey, id, typeObj.getJSONObject(SCHEMA_PROPERTIES), jsonData.getJSONObject(key)));
                    continue;
                case SCHEMA_TYPE_ARRAY:
                    result.addAll(jsonArray2InsertSql(tableName + "_" + key, tableKey, id, typeObj.getJSONObject(SCHEMA_ITEMS), jsonData.getJSONArray(key)));
                    continue;
                case SCHEMA_TYPE_NULL:
            }
        }
        String insertValuesSql = getInsertValuesSql(jsonData, properties, parentIdName, parentId, id);
        insertValuesSql = insertValuesSql.substring(0, insertValuesSql.length() - 1);
        StringBuilder sql = new StringBuilder("insert into ")
                .append(tableName)
                .append(getInsertFiledSql(properties, tableKey, parentIdName))
                .append(" values ")
                .append(insertValuesSql)
                .append(";");
        result.add(sql.toString());
        return result;
    }

    /**
     * JSON数组数据生成 clickHouse的Insert语句
     * @param tableName 指定表名
     * @param parentIdName 父节点主键名
     * @param parentId 父节点主键ID
     * @param items jsonSchema中的Items
     * @param jsonArrayData 数据表
     * @return Sql语句表
     */
    private static List<String> jsonArray2InsertSql(String tableName, String parentIdName, String parentId, JSONObject items, JSONArray jsonArrayData) {
        if (items == null || CollectionUtils.isEmpty(jsonArrayData)) {
            return new ArrayList<>();
        }
        List<String> result = new ArrayList<>();
        String type = items.getString(SCHEMA_TYPE);
        if (StringUtils.isEmpty(type)) {
            return new ArrayList<>();
        }
        switch (type) {
            case SCHEMA_TYPE_ARRAY:
                for (int i = 0; i < jsonArrayData.size(); i++) {
                    JSONArray jsonArray = jsonArrayData.getJSONArray(i);
                    result.addAll(jsonArray2InsertSql(tableName, parentIdName, parentId, items.getJSONObject(SCHEMA_ITEMS), jsonArray));
                }
                break;
            case SCHEMA_TYPE_OBJECT:
                for (int i = 0; i < jsonArrayData.size(); i++) {
                    JSONObject jsonObject = jsonArrayData.getJSONObject(i);
                    result.addAll(jsonObj2InsertSql(tableName, parentIdName, parentId, items.getJSONObject(SCHEMA_PROPERTIES), jsonObject));
                }
                break;
            case SCHEMA_TYPE_NULL:
        }
        return result;

    }

    /**
     * 生成insert语句的values
     * @param jsonData JSON数据
     * @param properties jsonSchema字段表
     * @param parentIdName 父节点主键名称
     * @param parentId 父节点主键ID
     * @param id 指定该节点主键ID
     * @return
     */
    private static String getInsertValuesSql(JSONObject jsonData, JSONObject properties, String parentIdName, String parentId, String id) {
        Set<String> keySet = properties.keySet();
        StringBuilder valuesSql = new StringBuilder(" ( '").append(id).append("', ");
        if (StringUtils.isNotEmpty(parentIdName)) {
            valuesSql.append("'").append(parentId).append("', ");
        }

        for (String filed : keySet) {
            JSONObject typeObj = properties.getJSONObject(filed);
            String type = typeObj.getString(SCHEMA_TYPE);
            if (StringUtils.isEmpty(type) || SCHEMA_TYPE_OBJECT.equals(type) || SCHEMA_TYPE_ARRAY.equals(type) || SCHEMA_TYPE_NULL.equals(type)) {
                continue;
            }
            if (SCHEMA_TYPE_INTEGER.equals(type) || SCHEMA_TYPE_NUMBER.equals(type)) {
                String value = jsonData.getString(filed);
                valuesSql.append(value == null ? 0 : value).append(", ");
            } else {
                String value = jsonData.getString(filed);
                valuesSql.append("'").append(value == null ? "" : value).append("'").append(", ");
            }
        }
        valuesSql.append("'").append(DateUtils.getDateStr("yyyy-MM-dd HH:mm:ss")).append("'),");

        return valuesSql.toString();
    }

    /**
     * 生成insert语句的字段表
     * @param filedList jsonSchema中的字段表
     * @param tableKey 表主键名
     * @param parentIdName 父级节点主键名
     * @return
     */
    private static String getInsertFiledSql(JSONObject filedList, String tableKey, String parentIdName) {
        Set<String> keySet = filedList.keySet();
        StringBuilder fieldSql = new StringBuilder(" ( ").append(tableKey).append(", ");
        if (StringUtils.isNotEmpty(parentIdName)) {
            fieldSql.append(parentIdName).append(", ");
        }
        for (String filed : keySet) {
            JSONObject typeObj = filedList.getJSONObject(filed);
            String type = typeObj.getString(SCHEMA_TYPE);
            if (StringUtils.isEmpty(type) || SCHEMA_TYPE_OBJECT.equals(type) || SCHEMA_TYPE_ARRAY.equals(type) || SCHEMA_TYPE_NULL.equals(type)) {
                continue;
            }
            fieldSql.append(filed).append(", ");
        }
        fieldSql.append(" jzx_create_date) ");
        return fieldSql.toString();
    }

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Run_the_ant

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

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

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

打赏作者

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

抵扣说明:

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

余额充值