简易SQL生成器

315 阅读2分钟

今天在使用Apifox的时候看到数据模型那一块能根据数据模型生成SQL但是不能添加约束,于是想着自己写一个SQL生成器,想到大多数情况下我们都是先设计模型然后才去写sql,我个人比较偏向于使用md的表格设计,于是写了这段根据md文档生成sql的代码,先看效果

【使用演示】 www.bilibili.com/video/BV1e7…

假如我们有以下表格

image.png

md语法是这样的

image.png

特征很明显,经过处理可以很容易构造出sql,于是有了下面代码(使用maven工程结构),向外暴露了一个静态方法convertToSQL调用这个方法传入一个md路径就会根据路径生成sql,将md文件的文件名作为数据库名

package com.neuedu.elm.utils;

import lombok.Data;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;


public class SQLBuilder {
    public static void main(String[] args) {
        SQLBuilder.convertToSQL("src/main/resources/test.md");
    }

    /**
     * 转换为SQL语句
     * @param path 文件路径
     * @return SQL语句
     */
    public static String convertToSQL(String path) {
        // 示例: src/main/resources/test.md
        File file = new File(path);
        List<SQLField> list = new ArrayList<>();
        System.out.println("文件名:" + file.getName());
        // 表名
        String tableName = file.getName().substring(0, file.getName().indexOf("."));
        try {
            Scanner sc = new Scanner(file);
            String line;
            // 先读两行跳过
            sc.nextLine();
            sc.nextLine();
            while (sc.hasNextLine()) {
                line = sc.nextLine();
                String[] arr = line.split("\|");
//                System.out.println(Arrays.toString(arr));
                // 如果数组长度为1,说明到了最后一行,跳出循环
                if (arr.length == 1 || arr.length == 0) {
                    break;
                }
                list.add(handler1(arr));
            }
            String sql = generateSQL(tableName, list);
            System.out.println(sql);
            return sql;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // 根据字段生成对象
    private static SQLField handler1(String[] arr) {
        // 如果数组为空或者长度为0,返回null (有空行)
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i].trim();
        }
        SQLField sqlField = new SQLField();
        try {
            // 从数组第二项开始,因为第一列是序号
            sqlField.setFieldName(arr[2]);
            sqlField.setType(arr[3]);
            sqlField.setSize(arr[4]);
            sqlField.setDefaultValue(arr[5]);
            sqlField.setConstraints(arr[6]);
            sqlField.setExplain(arr[7]);
        } catch (IndexOutOfBoundsException e) {
            System.out.println("数组越界异常");
        }
        return sqlField;
    }

    /**
     * 生成SQL语句
     * @param tableName 表名
     * @param list 字段列表
     * @return SQL语句
     */
    private static String generateSQL(String tableName, List<SQLField> list) {
        StringBuilder sb = new StringBuilder();
        sb.append("CREATE TABLE `" + tableName + "` (\n");

        for (int i = 0; i < list.size(); i++) {
            SQLField field = list.get(i);
            if (field == null) continue;
            sb.append("\t`" + field.getFieldName() + "` " + field.getType());
            if (field.getSize() != null && !"".equals(field.getSize())) {
                // 如果有括号就不加
                if (field.getSize().startsWith("(") && field.getSize().endsWith(")")) {
                    sb.append(field.getSize());
                } else {
                    sb.append("(" + field.getSize() + ")");
                }
            }
            // 约束处理外键约束不处理
            if (field.getConstraints() != null && !"".equals(field.getConstraints())) {
                if (field.getConstraints().contains("PK")) {
                    sb.append(" PRIMARY KEY");
                }
                if (field.getConstraints().contains("UN")) {
                    sb.append(" UNIQUE");
                }
                if (field.getConstraints().contains("NN")) {
                    sb.append(" NOT NULL");
                }
                if (field.getConstraints().contains("AI")) {
                    sb.append(" AUTO_INCREMENT");
                }
            }
            // 默认值处理
            if (field.getDefaultValue() != null && !"".equals(field.getDefaultValue())) {
                if (field.getDefaultValue().contains("CURRENT_TIMESTAMP") || field.getDefaultValue().equals("now()")) {
                    sb.append(" DEFAULT CURRENT_TIMESTAMP");
                } else if (field.getType().contains("varchar") || field.getType().contains("char") || field.getType().contains("mediumtext")) {
                    sb.append(" DEFAULT '" + field.getDefaultValue() + "'");
                } else if (field.getType().contains("int") || field.getType().contains("decimal")) {
                    sb.append(" DEFAULT " + field.getDefaultValue());
                } else if (field.getType().contains("date")) {
                    sb.append(" DEFAULT '" + field.getDefaultValue() + "'");
                }
            }
            // 添加描述
            if (field.getExplain()!= null &&!"".equals(field.getExplain())) {
                sb.append(" COMMENT '" + field.getExplain() + "'");
            }
            // 生成语句结尾的分号
            if (i != list.size() - 1) {
                sb.append(",\n");
            } else {
                sb.append("\n");
            }
        }
        sb.append(");");
        return sb.toString();
    }
}

// 字段所有内容的对象
@Data
class SQLField {
    private String fieldName;
    private String type;
    private String size;
    private String defaultValue;
    private String constraints;
    private String explain;
}

测试结果

image.png image.png

运行结果