原文地址
前言
网络上很多工具网站,将DDL
转换为Java
类,包括生成Entity
类,基本的增删改查控制层、接口层、实现层。基本上分为两个步骤,首先将各种类型/格式/写法的DDL
转换为统一结构的对象,然后再将对象写入指定字符串模板就好了,当然某些特殊情况需要根据字段特殊处理
第二步比较简单,总体来说定义一个字符串模板就可以,特殊情况不算太多。第一个步骤需要考虑的东西就太多了,我们选择直接去使用开源的包,这里我们使用的是sql-ddl-to-json-schema,一方面star
还不错,另一方面作者目前也是在积极维护
我们这里实现是转换为kotlin data class
,因为最近主要写Kotlin
,而且我稍微搜了一下,没有看到有比较好的DDL
转Kotlin
类的网站。本文使用的是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
即可
最后
再次声明,我不是前端工程师,所以前端代码可能写的不符合规范,只是为了完成功能,代码仅供参考噢