MySql生成ER【StarUML】文件
1. 背景
要画ER图,一个个打费时费力,StarUML文件打开是json。那么就有可能自动生成。
2. 效果
把表结构生成好,自己只要维护关系即可。

3. 代码
import lombok.Data;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author liwei
* @version 1.0
* @className MySqlToStarUML
* @date 2022/9/21 22:47
*/
public class MySqlToStarUML {
/**
* 自动生成代码入口
*
* @author liwei
* @date 2022-09-25 00:58:45
* @param args
* @return void
*/
public static void main(String[] args) {
localTest();
}
public static void localTest() {
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test_nacos?useUnicode=true&characterEncoding=UTF-8";
String userName = "root";
String password = "密码";
String filePath = "D:\\test_nacos.mdj";
List<Table> tableList = getTableList(driver, url, userName, password);
saveAsFileWriter(filePath, getProject(url, tableList));
System.out.println("===============生成成功================");
}
/**
* 获取项目字符串
*
* @author liwei
* @date 2023-03-16 18:37:01
* @param url
* 地址
* @param tableList
* 表集合
* @return {@link String}
*/
public static String getProject(String url, List<Table> tableList) {
String database = getDBByUrl(url);
Project project = new Project();
// 不能使用中文
project.setName(database);
project.set_id("AAAAAA_Project");
List<OwnedElement> erddatamodels = new ArrayList<>();
List<OwnedElement> ownedElements = new ArrayList<>();
ERDDataModel erdDataModel = new ERDDataModel();
erdDataModel.setName("Data Model1");
erdDataModel.set_id("AAAAAA_DataModel1");
erdDataModel.set_parent(project.get_id());
erddatamodels.add(erdDataModel);
ERDDiagram erdDiagram = new ERDDiagram();
erdDiagram.setName("ERDDiagram1");
erdDiagram.set_id("AAAAAA_ERDDiagram1");
erdDiagram.set_parent(erdDataModel.get_id());
ownedElements.add(erdDiagram);
for (Table table : tableList) {
table.set_parent(erdDataModel.get_id());
}
ownedElements.addAll(tableList);
erdDataModel.setOwnedElements(ownedElements);
project.setOwnedElements(erddatamodels);
return project.toString();
}
/**
* 通过url获取数据库
*
* @author liwei
* @date 2022-09-23 09:21:09
* @param url
* 地址
* @return {@link String}
*/
public static String getDBByUrl(String url) {
if (null == url || url.isEmpty()) {
throw new RuntimeException("地址为空");
}
if (url.indexOf(":") == 0 && url.length() <= 1) {
throw new RuntimeException("地址有误");
}
while (url.indexOf(":") > 0) {
url = url.substring(url.indexOf(":") + 1);
}
if (url.indexOf("?") > 0) {
url = url.substring(0, url.indexOf("?"));
}
if (url.indexOf("/") > 0) {
url = url.substring(url.indexOf("/") + 1);
}
return url;
}
/**
* 保存内容到文件
*
* @author liwei
* @date 2022-11-22 14:19:47
* @param filePath
* 文件路径
* @param content
* 内容
* @return void
*/
private static void saveAsFileWriter(String filePath, String content) {
FileWriter fwriter = null;
try {
fwriter = new FileWriter(filePath);
fwriter.write(content);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (null != fwriter) {
fwriter.flush();
fwriter.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
/**
* 获取表集合
*
* @author liwei
* @date 2022-11-22 14:20:24
* @param driver
* 驱动
* @param url
* 连接
* @param userName
* 账号
* @param password
* 密码
* @return {@link List< Table>}
*/
private static List<Table> getTableList(String driver, String url, String userName, String password) {
Connection connection;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, userName, password);
} catch (ClassNotFoundException e) {
throw new RuntimeException("加载驱动失败,找不到:" + driver);
} catch (SQLException e) {
throw new RuntimeException("获取数据库连接失败,请检查配置和日志", e);
}
String database = getDBByUrl(url);
String sqlTable = String.format("select * from information_schema.tables where TABLE_SCHEMA='%s'", database);
List<Map<String, String>> mapList = runSql(connection, sqlTable);
List<Table> tableList = new ArrayList<>();
for (int i = 0; i < mapList.size(); i++) {
Map<String, String> map = mapList.get(i);
Table table = new Table();
String tableId = String.valueOf(i + 1);
table.set_id(tableId);
table.setName(map.get("TABLE_NAME"));
table.setDocumentation(map.get("TABLE_COMMENT"));
String sqlColumn = String.format("select * from information_schema.columns where TABLE_SCHEMA='%s' and TABLE_NAME = '%s'", database, table.getName());
List<Map<String, String>> mapList2 = runSql(connection, sqlColumn);
List<Column> columnList = new ArrayList<>();
for (Map<String, String> stringMap : mapList2) {
Column column = new Column();
column.setTableId(tableId);
column.setName(stringMap.get("COLUMN_NAME"));
column.setType(stringMap.get("DATA_TYPE"));
String columnType = stringMap.get("COLUMN_TYPE");
if (columnType.indexOf("(") > 0) {
column.setLength(columnType.substring(columnType.indexOf("(") + 1, columnType.indexOf(")")));
} else {
column.setLength(stringMap.get("CHARACTER_MAXIMUM_LENGTH"));
}
column.setOrdinalPosition(Integer.parseInt(stringMap.get("ORDINAL_POSITION")));
column.setNullable("YES".equals(stringMap.get("IS_NULLABLE")));
column.setPrimaryKey("PRI".equals(stringMap.get("COLUMN_KEY")));
column.setUnique("UNI".equals(stringMap.get("COLUMN_KEY")));
columnList.add(column);
}
columnList.sort((c1, c2) -> c1.ordinalPosition - c2.getOrdinalPosition());
table.setColumns(columnList);
tableList.add(table);
}
close(null, connection, null);
return tableList;
}
/**
* 关闭连接
*
* @author liwei
* @date 2022-09-23 09:21:53
* @param pstmt
* 预编译
* @param conn
* 连接
* @param rs
* 结果集
* @return void
*/
public static void close(PreparedStatement pstmt, Connection conn, ResultSet rs) {
try {
if(null != rs) {
rs.close();
rs = null;
}
if(null != pstmt) {
pstmt.close();
pstmt = null;
}
if(null != conn) {
conn.close();
conn = null;
}
} catch (SQLException e) {
throw new RuntimeException("关闭数据库连接异常", e);
}
}
/**
* 运行sql
*
* @author liwei
* @date 2022-11-22 14:21:40
* @param conn
* 连接
* @param sql
* 执行的sql
* @return {@link List< Map< String, String>>}
*/
public static List<Map<String, String>> runSql(Connection conn, String sql) {
if (null == sql || sql.isEmpty()) {
throw new RuntimeException("执行的sql不可为空");
}
List<Map<String, String>> list = new ArrayList<>();
if(null == conn) {
throw new RuntimeException("获取数据库连接失败");
}
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
Map<String, String> map = new HashMap<>();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
map.put(metaData.getColumnName(i), rs.getString(i));
}
list.add(map);
}
} catch (SQLException e) {
throw new RuntimeException("执行sql异常", e);
} finally {
close(pstmt, null, rs);
}
return list;
}
@Data
static class Table extends OwnedElement {
private String _type = "ERDEntity";
private String documentation;
private List<Column> columns;
@Override
public String toString() {
return "{" +
"\"_type\":\"" + _type + '\"' +
", \"_id\":\"" + super._id + '\"' +
", \"_parent\":{\"$ref\":\"" + super._parent + "\"}" +
", \"name\":\"" + super.name + " " + documentation + '\"' +
", \"documentation\":\"" + documentation + '\"' +
", \"columns\":" + columns +
'}';
}
}
@Data
static class Column {
private String _type = "ERDColumn";
private String name;
private String tableId;
private String type;
private String length;
// UNI、PRI
private String columnKey;
private int ordinalPosition;
private Boolean primaryKey;
private Boolean unique;
private Boolean nullable;
@Override
public String toString() {
return "{" +
"\"_type\":\"ERDColumn\"" +
", \"_parent\":{\"$ref\":\"" + tableId + "\"}" +
", \"name\":\"" + name + '\"' +
", \"type\":\"" + type + '\"' +
(null != length ? ", \"length\":\"" + length + '\"' : "") +
(primaryKey ? ", \"primaryKey\":\"" + primaryKey + "\"" : "") +
(unique ? ", \"unique\":\"" + unique + "\"" : "") +
(nullable ? ", \"nullable\":\"" + nullable + "\"" : "") +
'}';
}
}
@Data
static class Project extends OwnedElement {
private String _type = "Project";
@Override
public String toString() {
return "{" +
"\"_type\":\"Project\"" +
", \"_id\":\"" + super._id + '\"' +
", \"name\":\"" + super.name + '\"' +
", \"ownedElements\":" + super.ownedElements +
"}";
}
}
@Data
static class OwnedElement {
private String _type;
private String _id;
private String _parent;
private String name;
private List<OwnedElement> ownedElements;
}
@Data
static class ERDDataModel extends OwnedElement {
private String _type = "ERDDataModel";
@Override
public String toString() {
return "{" +
"\"_type\":\"ERDDataModel\"" +
", \"_id\":\"" + super._id + '\"' +
", \"_parent\":{\"$ref\":\"" + super._parent + "\"}" +
", \"name\":\"" + super.name + '\"' +
", \"ownedElements\":" + super.ownedElements +
"}";
}
}
@Data
static class ERDDiagram extends OwnedElement {
private String _type = "ERDDiagram";
@Override
public String toString() {
return "{" +
"\"_type\":\"ERDDiagram\"" +
", \"_id\":\"" + super._id + '\"' +
", \"_parent\":{\"$ref\":\"" + super._parent + "\"}" +
", \"name\":\"" + super.name + '\"' +
(null != super.ownedElements ? ", \"ownedViews\":" + super.ownedElements : "") +
"}";
}
}
@Data
static class ERDEntityView extends OwnedElement {
private String _type = "ERDEntityView";
private String tableId;
@Override
public String toString() {
return "{" +
"\"_type\":\"ERDEntityView\"" +
", \"model\":{\"" + tableId + "\"}" +
(null != super.ownedElements ? ", \"subViews\":" + super.ownedElements : "") +
"}";
}
}
}
MySql生成ER【StarUML】文件的更多相关文章
- PowerDesigner连接 MySQL 生成 ER图
powerdesigner 16.5 http://www.pcsoft.com.cn/soft/27495.html jdk 1.8 32位 https://mirrors.huaweicloud. ...
- MySQL数据表生成ER图
遇到没有说明文档的数据库的时候,一张一张表去分析,需要花费很长时间和精力. 幸好有一些工具,可以帮助我们生成ER图,这样看起来就一目了然: 下面我将自己的一次实践记录于下,供参考: 1.下载并安装工具 ...
- EA逆向生成数据库E-R图(mysql数据库-->ER图)
[1]选择 工具-->ODBC-Data-Sources [2]ODBC数据源管理器 ,点击添加 [3]选择一个mysql驱动 ,点击MySQL ODBC 5.1 Driver(其它同理), ...
- 利用powerdesigner反向数据库结构,生成ER图
参考月下狼~图腾~:<利用powerdesigner反向数据库结构,生成ER图> https://www.zybuluo.com/Jpz/note/123582 首先新建一个"P ...
- 【PowerDesigner】【4】连接数据库并生成ER图
文字版: 1,File→Reverse Engineer→Database...., 2,新窗口database reverse engineering打开后,填写名称(Model name),选择数 ...
- MySQL命令执行sql文件的两种方法
MySQL命令执行sql文件的两种方法 摘要:和其他数据库一样,MySQL也提供了命令执行sql脚本文件,方便地进行数据库.表以及数据等各种操作.下面笔者讲解MySQL执行sql文件命令的两种方法,希 ...
- myBatis自动生成相关代码文件配置(Maven)
pom.xml文件添加配置 <build> <finalName>generator</finalName> <plugins> <!-- mav ...
- MySQL服务读取参数文件my.cnf的规律研究探索
在MySQL中,它是按什么顺序或规律去读取my.cnf配置文件的呢?其实只要你花一点功夫,实验测试一下就能弄清楚,下面的实验环境为5.7.21 MySQL Community Server.其它版本如 ...
- 利用TPC-H为MYSQL生成数据
## 利用TPC-H为MYSQL生成数据 导言 这篇文章是看了joyee写的TPC-H数据导入MySQL教程以及另一篇网上的MySQL TPCH测试工具简要手册 后写的,有些内容是完全转载自以上两篇文 ...
- MySQL体系结构之物理文件
一.MySQL日志文件 mysql日志文件及功能: 日志文件 功能 错误日志 记录启动.停止.运行过程中mysqld时出现的问题 通用日志 记录建立客户端连接和执行的语句 二进制日志 记录更改数据的所 ...
随机推荐
- ffmpeg将常见视频格式转换为mp4
1,avi.mkv.mp4等格式转为mp4 ffmpeg -i 1.avi -c copy 1.mp4 2,wmv.asf等格式转为mp4 ffmpeg -i 1.asf 1.mp4
- [2002年NOIP提高组] 均分纸牌
有 N 堆纸牌,编号分别为 1,2,-, N.每堆上有若干张,但纸牌总数必为 N 的倍数.可以在任一堆上取若于张纸牌,然后移动.移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上:在编 ...
- 复杂的光照与更复杂的阴影实现过程——ShaderCP9
--20.8.28 这章的内容看了很久,也有很多复杂的内容.中途还有事情耽搁了一会.开学后就继续好好记录努力. 我们在游戏中能看到的让人觉得真实感的来源之一就是真实的光照以及光照所产生的阴影.下面的内 ...
- Jmeter添加BeanShell后置处理程序保存响应结果
对于某些请求,无法通过保存响应到文件这个组件来进行保存(会出现UNKNOW文件类型). 那么就可以通过BeanShell后置处理程序来进行将响应结果直接输出到文件,并可以直接指定文件名和后缀. imp ...
- python机器学习——BP(反向传播)神经网络算法
背景与原理: BP神经网络通常指基于误差反向传播算法的多层神经网络,BP算法由信号的前向传播和反向传播两个过程组成,在前向传播的过程中,输入从输入层进入网络,经过隐含层逐层传递到达输出层输出,如果输出 ...
- bootstrapTable insertRow 新增行保留原数据
思路:保留原数据,然后新增行. var optionsxx = {//省略xxx: columns: [{ checkbox: true}, { field: 'id', title: '主键', c ...
- ??????FormDataAccess
using Genersoft.Fms.Center.Pub.Com;using Genersoft.Platform.AdpBizIntegration.Entity;using Genersoft ...
- MySQL8.0使用GROUP BY的问题
当使用group by的语句中,select后面跟的列,在group by后面没有时,会报以下错误: Expression #2 of SELECT list is not in GROUP BY c ...
- 5ppm高精度自动同步标准化考场时钟系统
自动同步标准化考场时钟系统------专业LED时钟厂家![点击进入] 学校考场医院车站GPS/NTP网络校时之组联网对时精度达5ppm原理剖析. 时间精度是根据各个用户所要求对LE ...
- 二,使用axios
1,下载https://unpkg.com/axios@1.3.2/dist/axios.min.js保存在js目录下,命名为axios.js 2,http.js let baseUrl = &quo ...