2

MySql生成ER【StarUML】文件 - xiaostudy

 1 year ago
source link: https://www.cnblogs.com/xiaostudy/p/17224092.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

MySql生成ER【StarUML】文件

要画ER图,一个个打费时费力,StarUML文件打开是json。那么就有可能自动生成。

把表结构生成好,自己只要维护关系即可。

image
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 : "") +
                    "}";
        }
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK