构建自己的DDL转对象类在线工具(Kotlin为例)

原文地址

原文链接

前言

网络上很多工具网站,将DDL转换为Java类,包括生成Entity类,基本的增删改查控制层、接口层、实现层。基本上分为两个步骤,首先将各种类型/格式/写法的DDL转换为统一结构的对象,然后再将对象写入指定字符串模板就好了,当然某些特殊情况需要根据字段特殊处理

第二步比较简单,总体来说定义一个字符串模板就可以,特殊情况不算太多。第一个步骤需要考虑的东西就太多了,我们选择直接去使用开源的包,这里我们使用的是sql-ddl-to-json-schema,一方面star还不错,另一方面作者目前也是在积极维护

我们这里实现是转换为kotlin data class,因为最近主要写Kotlin,而且我稍微搜了一下,没有看到有比较好的DDLKotlin类的网站。本文使用的是JS,是直接作为本站工具类的,有需要的小伙伴可以直接跳转参考,代码生成

实现

引用包

"sql-ddl-to-json-schema": "^4.1.0"

解析出的对象,可以参考源代码-datatype,也可以自己打日志看,代码如下

import {Parser} from 'sql-ddl-to-json-schema'

export const defaultSql = `
CREATE TABLE \`goods\` (
  \`item_id\` varchar(20) NOT NULL COMMENT '商品id',
  \`item_name\` varchar(200) NOT NULL COMMENT '商品标题',
  \`item_desc\` varchar(200)  COMMENT '商品描述',
  \`item_price\` decimal(8,2)  NOT NULL DEFAULT 0 COMMENT '商品价格',
  \`status\` int NOT NULL COMMENT '商品状态,0-正常,1- 下架 2-删除',
  \`create_time\` datetime NOT NULL COMMENT '创建时间',
  \`update_time\` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (\`goods_id\`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品表';
`;

//sql data type to kotlin map
let sqlDataType2KotlinMap = new Map([
    ["int", "Int"], ["bit", "Int"], ["binary", "Int"], ["bit", "Int"],
    ["decimal", "BigDecimal"], ["float", "BigDecimal"], ["double", "BigDecimal"], ["boolean", "Boolean"],
    ["date", "Date"], ["time", "Date"], ["datetime", "Date"], ["timestamp", "Date"],
    ["blob", "String"], ["text", "String"], ["char", "String"], ["varchar", "String"],
])

let defaultValueMap = new Map([
    ["Int", " = 0"], ["String", " = \"\""], [""], ["Double", " = 0.0"], ["BigDecimal", " = BigDecimal.ZERO"],
    ["Boolean", " = false"], ["Date", " = Date()"], ["LocalDateTime", " = LocalDateTime.now()"]
])

//kotlin code result
let resCode = ""

//options
export let convertOptions = {
    packageName: "com.aster.extend",
    isLocalDateTime: false,
    isNeedComment: true,
    isCamelCase: true,
    isBigDecimal: true,
    isAllNullable: false,
    isSetDefaultValue: true,
}

//parser init
const parser = new Parser('mysql');
let tableObj = {}

function parseSql(sql) {
    try {
        const compactJsonTablesArray = parser.feed(sql).toCompactJson(parser.results);
        tableObj = compactJsonTablesArray[0]
    } catch (err) {
        return false
    }
    return true
}

//change line
function wrapWrite(text, textOther = "") {
    if (text) {
        return text + "\n" + textOther
    }
    return textOther
}

function camelBuilder(name, firstUpper = false) {
    if (!convertOptions.isCamelCase) {
        return name
    }
    let nameArr = name.split('')
    let upperIndex = firstUpper ? 0 : -1
    for (let index = 0; index < name.length; ++index) {
        if (upperIndex === index) {
            nameArr[index] = nameArr[index].toUpperCase()
            upperIndex = -1
        }
        if (nameArr[index] === '_') {
            upperIndex = index + 1
        }
    }
    return nameArr.join('').replaceAll('_', '')
}

//add package
function addPackage() {
    //package
    resCode = wrapWrite(resCode, 'package ' + convertOptions.packageName)
    //end
    resCode = wrapWrite(resCode)
}

function addImport() {
    const dataTypeArr = tableObj.columns.map(col => col.type.datatype)
    //date time
    if (dataTypeArr.includes("timestamp") || dataTypeArr.includes("date") ||
        dataTypeArr.includes("time") || dataTypeArr.includes("datetime")) {
        if (convertOptions.isLocalDateTime) {
            resCode = wrapWrite(resCode, "import java.time.LocalDateTime")
        } else {
            resCode = wrapWrite(resCode, "import java.util.Date")
        }
    }
    //decimal
    if (dataTypeArr.includes("decimal") && convertOptions.isBigDecimal) {
        resCode = wrapWrite(resCode, "import java.math.BigDecimal")
    }
    //end
    resCode = wrapWrite(resCode)
}

function addProperty() {
    for (let index in tableObj.columns) {
        let curColumn = tableObj.columns[index]

        let curName = camelBuilder(curColumn.name)
        let curType = sqlDataType2KotlinMap.get(curColumn.type.datatype)
        let isAllowNull = curColumn.options.nullable || convertOptions.isAllNullable
        let isAllowNullNotation = isAllowNull ? "?" : ""

        if (convertOptions.isLocalDateTime && "Date" === curType) {
            curType = "LocalDateTime"
        }
        if (!convertOptions.isBigDecimal && "BigDecimal" === curType) {
            curType = "Double"
        }
        if (!curType) {
            curType = "String"
        }

        if (convertOptions.isNeedComment) {
            let comment = curColumn.options.comment ? curColumn.options.comment : curName
            resCode = wrapWrite(resCode, `\n    /**\n     * ${comment}\n     */`)
        }

        let defaultValueStr = ""
        if (convertOptions.isSetDefaultValue) {
            defaultValueStr = " = null"
            if (!isAllowNull) {
                defaultValueStr = defaultValueMap.get(curType)
            }
        }

        resCode = wrapWrite(resCode,
            `    var ${curName}: ${curType}${isAllowNullNotation}${defaultValueStr},`)
    }
}

function addBody() {
    resCode = wrapWrite(resCode, "data class " +
        camelBuilder(tableObj.name, true) + " (")
    addProperty()
    resCode = wrapWrite(resCode, ")")
}

function buildResCode() {
    resCode = ""
    addPackage()
    addImport()
    addBody()
    return resCode
}

export function ddlConvertKotlinDataClass(sql) {
    if (parseSql(sql) && tableObj) {
        return buildResCode()
    }
    return ""
}

使用的时候,先设置配置项convertOptions,然后调用ddlConvertKotlinDataClass(sql)传入DDL即可

最后

再次声明,我不是前端工程师,所以前端代码可能写的不符合规范,只是为了完成功能,代码仅供参考噢

原文地址

原文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值