侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

抽象思维实践——ddl2plantuml开发记录

2022-07-08 星期五 / 0 评论 / 0 点赞 / 46 阅读 / 9838 字

项目源码地址: github.com/wangyuheng/…背景利用plantuml绘制架构评审图时,发现数据库ER图手写字段信息成本太大,需要一个把DB表结构转换为plantuml格式的工具。搜索

项目源码地址: github.com/wangyuheng/…

背景

利用plantuml绘制架构评审图时,发现数据库ER图手写字段信息成本太大,需要一个把DB表结构转换为plantuml格式的工具。搜索了一番,没有发现支持工具,所以准备手撸一个,并记录下设计及编码实现的过程。

需求

一句话需求: 读取数据库表结构,转换为plantuml格式的ER图。

设计

根据需求抽象出下列概念

基础元素(一个输入一个输出)

  1. ER -> plantuml格式er
  2. db_schema -> 数据库结构,ddl语句是其中一种实现形式

扩展概念

  1. table -> 表结构信息
  2. template -> 模板,定义er图输出格式

操作行为

  1. reader -> 读取数据库结构,识别 table
  2. parser -> 根据 tabletemplate 转换为ER
  3. writer -> 输出ER图文件

整体交互

storage "Context" {    node ddl    node db_schema    node ER    node template    node table    usecase parser    usecase reader    usecase writer}ddl -down-|> db_schemadb_schema -down-> readerreader -> tabletable -> parserparser <-up- templateparser -down-> writerwriter -> ER

选型

都是基本的文件及String操作,通过 druid 进行sql解析

编码实现

Reader

读取ddl.sql文件,解析成 table

interface Reader {    fun read(dbType: String? = DEFAULT_DB_TYPE): Iterable<Table>    fun extract(dbType: String, sql: String): Table {    ...        }}class FileReader(private val path: String) : Reader {    override fun read(dbType: String?): Iterable<Table> {        return Files.readAllLines(Paths.get(path))                .filter { !it.startsWith("#") }                .joinToString("")                .split(";")                .filter { it.isNotBlank() }                .map { extract(dbType?: DEFAULT_DB_TYPE, it) }                .toList()    }}

Writer

template通过resource文件管理,接收table输出plantuml格式ER

interface Writer {    fun write(tables: Iterable<Table>)    fun parse(tables: Iterable<Table>): String {        val template = Thread.currentThread().contextClassLoader.getResource("dot.template")!!.readText()        val content = tables.joinToString("") { table ->            val columns = table.columnList.joinToString("/n") { "${it.notNullNameWrapper()} ${it.type} ${it.defaultValue} ${it.comment}" }            "Table(${table.name}, /"${table.name}//n(${table.comment})/"){ /n $columns + /n } /n"        }        return template.replace("__content__", content)    }    private fun Column.notNullNameWrapper(): String {        return if (this.notNull) {            "not_null(${this.name})"        } else {            this.name        }    }}class FileWriter(private val path: String) : Writer {    override fun write(tables: Iterable<Table>) {        Files.write(Paths.get(path), parse(tables).toByteArray())    }}

Main

fun main(args: Array<String>) {    val inPath = args[0]    val outPath = args[1]    val dbType = args.getOrNull(2)    FileReader(inPath).read(dbType)            .apply { FileWriter(outPath).write(this) }}

效果

java -jar ddl2plantuml.jar ddl.sql er.puml

程序会读取当前目录下的ddl.sql文件,并转换生成er.puml文件。

@startuml!define Table(name,desc) class name as "desc" << (T,#FFAAAA) >>!define primary_key(x) <color:red><b>x</b></color>!define unique(x) <color:green>x</color>!define not_null(x) <u>x</u>hide methodshide stereotypesTable(table_1, "table_1/n(This is table 1)"){ not_null(id) bigint  column_1  not_null(prod_name) varchar  column_2  not_null(prod_type) tinyint '0' column_3 0:活期 1:定期  not_null(start_time) time  停止交易开始时间  not_null(end_time) time  停止交易结束时间  not_null(online_type) tinyint '0' 0:上线 1:未上线  not_null(prod_info) varchar '' 产品介绍  not_null(over_limit) tinyint '0' 超额限制 0:限制 1:不限制  not_null(created_time) datetime CURRENT_TIMESTAMP   not_null(updated_time) datetime CURRENT_TIMESTAMP   }    Table(table_2, "table_2/n(This is table 2)"){ not_null(id) bigint    not_null(user_id) bigint  用户id  not_null(user_name) varchar  用户名称  not_null(prod_id) bigint  产品id  interest_date dateNULL计息日期  not_null(created_time) datetime CURRENT_TIMESTAMP 创建时间  not_null(updated_time) datetime CURRENT_TIMESTAMP 更新时间  }    Table(table_3, "table_3/n(This is table 3)"){ not_null(id) bigint    not_null(user_id) bigint  用户id  not_null(user_name) varchar  用户名称  not_null(prod_id) bigint  产品id  interest_date dateNULL计息日期  not_null(created_time) datetime CURRENT_TIMESTAMP 创建时间  not_null(updated_time) datetime CURRENT_TIMESTAMP 更新时间  } @enduml

.

.

广告 广告

评论区