├── lib └── lib.txt ├── .gitignore ├── doc.jpg ├── table.jpg ├── summary.jpg ├── sqljdbc42.jar ├── bin ├── start.bat └── start.sh ├── src └── main │ ├── java │ └── cn │ │ └── enilu │ │ └── tool │ │ └── database │ │ └── doc │ │ └── generator │ │ ├── bean │ │ ├── Constants.java │ │ ├── ColumnVo.java │ │ ├── TableVo.java │ │ └── DdgDataSource.java │ │ ├── doc │ │ ├── Html2DocConverter.java │ │ └── WordGenerator.java │ │ ├── database │ │ ├── Oracle.java │ │ ├── PostgreSQL.java │ │ ├── MySQL.java │ │ ├── SqlServer.java │ │ ├── Mongo.java │ │ └── Generator.java │ │ └── Main.java │ └── resources │ ├── database-mongo.html │ └── database.html ├── LICENSE ├── dist.xml ├── README.md └── pom.xml /lib/lib.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea/ 3 | target/ 4 | *-doc 5 | lib/*.jar -------------------------------------------------------------------------------- /doc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enilu/database-doc-generator/HEAD/doc.jpg -------------------------------------------------------------------------------- /table.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enilu/database-doc-generator/HEAD/table.jpg -------------------------------------------------------------------------------- /summary.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enilu/database-doc-generator/HEAD/summary.jpg -------------------------------------------------------------------------------- /sqljdbc42.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enilu/database-doc-generator/HEAD/sqljdbc42.jar -------------------------------------------------------------------------------- /bin/start.bat: -------------------------------------------------------------------------------- 1 | title "database-doc-generator" 2 | cd .. 3 | set JAVA_OPTIONS=-Djava.ext.dirs="lib" 4 | set JAVA_OPTIONS2= -Dfile.encoding="UTF-8" 5 | 6 | java -classpath "%CLASSPATH%" %JAVA_OPTIONS% %JAVA_OPTIONS2% cn.enilu.tool.database.doc.generator.Main 7 | 8 | pause 9 | 10 | -------------------------------------------------------------------------------- /bin/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_PATH=`readlink -f "$0"`; 4 | cd `dirname ${SCRIPT_PATH}` 5 | cd .. 6 | 7 | CP="" 8 | if [ -d target/classes ]; then 9 | CP=$CP:target/classes 10 | fi 11 | 12 | for jar in `/bin/ls -1 lib/*.jar` 13 | do 14 | CP=$CP:$jar 15 | done 16 | 17 | java -Xms256M -Xmx512M -cp $CP cn.enilu.tool.database.doc.generator.Main 18 | -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/bean/Constants.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator.bean; 2 | 3 | /** 4 | * 5 | * Constants 6 | * @Author enilu 7 | * @Date 2021/4/28 10:19 8 | * @Version 1.0 9 | */ 10 | public class Constants { 11 | public static final int DB_MYSQL= 1; 12 | public static final int DB_ORACLE= 2; 13 | public static final int DB_POSTGRESQL= 3; 14 | public static final int DB_SQLSERVER= 4; 15 | public static final int DB_MONGO= 5; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 enilu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dist.xml: -------------------------------------------------------------------------------- 1 | 4 | dist 5 | 6 | tar.gz 7 | 8 | 9 | 10 | ${project.basedir} 11 | / 12 | 13 | lib/**/* 14 | bin/**/* 15 | README* 16 | 17 | 18 | 19 | 20 | 21 | 22 | ${project.basedir}/target 23 | /lib 24 | 25 | database-doc-generator*.jar 26 | 27 | 28 | 29 | ${project.basedir}/target/classes/ 30 | / 31 | 32 | database.html 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/bean/ColumnVo.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator.bean; 2 | 3 | /** 4 | * ColumnVo 5 | * 6 | * @author zt 7 | * @version 2018/10/6 0006 8 | */ 9 | public class ColumnVo { 10 | private String name; 11 | private String type; 12 | private String key; 13 | private String isNullable; 14 | private String comment; 15 | 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | 25 | public String getType() { 26 | return type; 27 | } 28 | 29 | public void setType(String type) { 30 | this.type = type; 31 | } 32 | 33 | public String getKey() { 34 | return key; 35 | } 36 | 37 | public void setKey(String key) { 38 | this.key = key; 39 | } 40 | 41 | public String getIsNullable() { 42 | return isNullable; 43 | } 44 | 45 | public void setIsNullable(String isNullable) { 46 | this.isNullable = isNullable; 47 | } 48 | 49 | public String getComment() { 50 | return comment; 51 | } 52 | 53 | public void setComment(String comment) { 54 | this.comment = comment; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/resources/database-mongo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 |

${dbName}数据库设计文档

14 |

表汇总

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | <#list tables as item> 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
名称备注
${item.table}${item.comment?default('')}
34 |

表明细

35 | <#list tables as item> 36 |
37 |

${item.table}

38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | <#list item.columns as column> 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
列名类型注释
${column.name}${column.type}${column.comment?default('')}
56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/main/resources/database.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 |

${dbName}数据库设计文档

14 |

表汇总

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | <#list tables as item> 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
名称备注记录数数据量
${item.table}${item.comment?default('')}${item.rows?default('')}${item.dataLengthHuman?default('')}
36 |

表明细

37 | <#list tables as item> 38 |
39 |

${item.comment?default('')}(${item.table})

40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | <#list item.columns as column> 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
列名类型KEY可否为空注释
${column.name}${column.type}${column.key?default('')}${column.isNullable?default('')}${column.comment?default('')}
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # database-doc-generator 2 | 数据库文档生成器 3 | 4 | - 该工具根据给定的链接生成数据库文档,如果你嫌powerdesigner太重,那么可以试试该工具。 5 | - 支持的数据库类型: 6 | - MySQL 7 | - Oracle 8 | - SQLServer 9 | - MongoDB 10 | - PostgreSQL 11 | 12 | - 你可以下载[release](https://github.com/enilu/database-doc-generator/releases/tag/1.3.0)包来或者下载源代码来使用。 13 | - 如果使用源代码,需要先克隆该项目后运行mvn package打包,然后运行发布报中bin/start.bat 14 | - 运行程序后按照下面提示输入对应数据库参数: 15 | 16 | ```bash 17 | choose database: 18 | 1:mysql 19 | 2:oracle 20 | 3:PostgreSQL 21 | Select the appropriate numbers choose database type 22 | (Enter 'c' to cancel): 3 23 | input database name: 24 | gunslite 25 | input host: 26 | localhost 27 | input port: 28 | 5432 29 | input username: 30 | enilu 31 | input password: 32 | 123456 33 | 34 | ``` 35 | - 输入完成后回车,即可生成数据库文档目录${dbname}-doc,目录中文档有三种形式:单文件html,word,markdown 36 | 37 | 其中markdown可以用来生成html用于在线查看数据库文档: 38 | 39 | ![doc](doc.jpg) 40 | 41 | - 确保安装了gitbook后,进入上述文件目录的命令行窗口运行:gitbook serve 42 | ```bash 43 | E:\\database-doc-generator-20181006100721\guns-lite-doc>gitbook serve 44 | openssl config failed: error:02001003:system library:fopen:No such process 45 | Live reload server started on port: 35729 46 | Press CTRL+C to quit ... 47 | 48 | info: 7 plugins are installed 49 | info: loading plugin "livereload"... OK 50 | info: loading plugin "highlight"... OK 51 | info: loading plugin "search"... OK 52 | info: loading plugin "lunr"... OK 53 | info: loading plugin "sharing"... OK 54 | info: loading plugin "fontsettings"... OK 55 | info: loading plugin "theme-default"... OK 56 | info: found 15 pages 57 | info: found 0 asset files 58 | info: >> generation finished with success in 1.6s ! 59 | 60 | Starting server ... 61 | Serving book on http://localhost:4000 62 | ``` 63 | - 访问 http://localhost:4000,即可在线查看数据库文档 64 | 65 | ![summary](summary.jpg) 66 | 67 | ![table](table.jpg) -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/bean/TableVo.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * TableVo 7 | * 8 | * @author zt 9 | * @version 2018/10/6 0006 10 | */ 11 | public class TableVo { 12 | private String table; 13 | private String comment; 14 | /** 15 | * 表的记录数 16 | */ 17 | private Long rows; 18 | /** 19 | * 表数据占用空间大小,单位(字节数) 20 | */ 21 | private Long dataLength=0L; 22 | /** 23 | * 表数据占用空间大小,易于阅读的格式XX GB XX Mb XX KB 24 | */ 25 | public String dataLengthHuman="0"; 26 | private List columns; 27 | 28 | public String getTable() { 29 | return table; 30 | } 31 | 32 | public void setTable(String table) { 33 | this.table = table; 34 | } 35 | 36 | public String getComment() { 37 | return comment; 38 | } 39 | 40 | public void setComment(String comment) { 41 | this.comment = comment; 42 | } 43 | 44 | public List getColumns() { 45 | return columns; 46 | } 47 | 48 | public void setColumns(List columns) { 49 | this.columns = columns; 50 | } 51 | 52 | public Long getRows() { 53 | return rows; 54 | } 55 | 56 | public void setRows(Long rows) { 57 | this.rows = rows; 58 | } 59 | 60 | public Long getDataLength() { 61 | return dataLength; 62 | } 63 | 64 | public void setDataLength(Long dataLength) { 65 | this.dataLength = dataLength; 66 | } 67 | 68 | public String getDataLengthHuman() { 69 | long temp = 0; 70 | String humanLength = "0KB"; 71 | if(dataLength>1024){ 72 | temp = dataLength/1024; 73 | humanLength = temp+"KB"; 74 | } 75 | if(temp>1024){ 76 | temp = temp/1024; 77 | humanLength = temp+"MB"; 78 | } 79 | if(temp>1024){ 80 | temp = temp/1024; 81 | humanLength = temp+"GB"; 82 | } 83 | setDataLengthHuman(humanLength); 84 | return dataLengthHuman; 85 | } 86 | 87 | public void setDataLengthHuman(String dataLengthHuman) { 88 | this.dataLengthHuman = dataLengthHuman; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/bean/DdgDataSource.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator.bean; 2 | 3 | import org.nutz.dao.impl.SimpleDataSource; 4 | 5 | /** 6 | * 自定义数据源 7 | * 8 | * @Author enilu 9 | * @Date 2021/4/28 10:14 10 | * @Version 1.0 11 | */ 12 | 13 | public class DdgDataSource { 14 | private int dbType; 15 | private String ip; 16 | private String port; 17 | private String user; 18 | private String pass; 19 | private String dbName; 20 | 21 | public SimpleDataSource getDs(){ 22 | SimpleDataSource dataSource = new SimpleDataSource(); 23 | 24 | if (Constants.DB_MYSQL == dbType) { 25 | dataSource.setJdbcUrl("jdbc:mysql://" + ip + ":" + port + "/" + dbName); 26 | } else if (Constants.DB_ORACLE == dbType) { 27 | dataSource.setJdbcUrl("jdbc:oracle:thin:@" + ip + ":" + port + ":" + dbName); 28 | } else if (Constants.DB_POSTGRESQL == dbType) { 29 | dataSource.setJdbcUrl("jdbc:postgresql://" + ip + ":" + port + "/" + dbName); 30 | } else if (Constants.DB_SQLSERVER == dbType) { 31 | dataSource.setJdbcUrl("jdbc:sqlserver://" + ip + ":" + port + ";database=" + dbName); 32 | } 33 | dataSource.setUsername(user); 34 | dataSource.setPassword(pass); 35 | return dataSource; 36 | } 37 | 38 | public int getDbType() { 39 | return dbType; 40 | } 41 | 42 | public void setDbType(int dbType) { 43 | this.dbType = dbType; 44 | } 45 | 46 | public String getIp() { 47 | return ip; 48 | } 49 | 50 | public void setIp(String ip) { 51 | this.ip = ip; 52 | } 53 | 54 | public String getPort() { 55 | return port; 56 | } 57 | 58 | public void setPort(String port) { 59 | this.port = port; 60 | } 61 | 62 | public String getUser() { 63 | return user; 64 | } 65 | 66 | public void setUser(String user) { 67 | this.user = user; 68 | } 69 | 70 | public String getPass() { 71 | return pass; 72 | } 73 | 74 | public void setPass(String pass) { 75 | this.pass = pass; 76 | } 77 | 78 | public String getDbName() { 79 | return dbName; 80 | } 81 | 82 | public void setDbName(String dbName) { 83 | this.dbName = dbName; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/doc/Html2DocConverter.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator.doc; 2 | 3 | import org.apache.poi.poifs.filesystem.DirectoryEntry; 4 | import org.apache.poi.poifs.filesystem.POIFSFileSystem; 5 | 6 | import java.io.*; 7 | 8 | /** 9 | * Html2DocConverter 10 | * 11 | * @author zt 12 | * @version 2019/1/12 0012 13 | */ 14 | public class Html2DocConverter { 15 | 16 | private String inputPath; // 输入文件路径,以.html结尾 17 | private String outputPath; // 输出文件路径,以.doc结尾 18 | 19 | public Html2DocConverter(String inputPath, String outputPath) { 20 | super(); 21 | this.inputPath = inputPath; 22 | this.outputPath = outputPath; 23 | } 24 | 25 | /** 26 | * 读取html文件到word 27 | * 28 | * @param filepath 29 | * html文件的路径 30 | * @return 31 | * @throws Exception 32 | */ 33 | public boolean writeWordFile() throws Exception { 34 | 35 | InputStream is = null; 36 | FileOutputStream fos = null; 37 | 38 | // 1 找不到源文件, 则返回false 39 | File inputFile = new File(this.inputPath); 40 | if (!inputFile.exists()) { 41 | return false; 42 | } 43 | 44 | File outputFile = new File(this.outputPath); 45 | // 2 如果目标路径不存在 则新建该路径 46 | if (!outputFile.getParentFile().exists()) { 47 | outputFile.getParentFile().mkdirs(); 48 | } 49 | 50 | try { 51 | 52 | // 3 将html文件内容写入doc文件 53 | is = new FileInputStream(inputFile); 54 | POIFSFileSystem poifs = new POIFSFileSystem(); 55 | DirectoryEntry directory = poifs.getRoot(); 56 | directory.createDocument( 57 | "WordDocument", is); 58 | 59 | fos = new FileOutputStream(this.outputPath); 60 | poifs.writeFilesystem(fos); 61 | 62 | System.out.println("转换word文件完成!"); 63 | 64 | return true; 65 | } catch (IOException e) { 66 | e.printStackTrace(); 67 | } finally { 68 | if (fos != null) { 69 | fos.close(); 70 | } 71 | if (is != null) { 72 | is.close(); 73 | } 74 | } 75 | 76 | return false; 77 | } 78 | public static void main(String[] args) throws Exception { 79 | 80 | new Html2DocConverter("G:/123.html" , "G:/temp5.doc").writeWordFile(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/database/Oracle.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator.database; 2 | 3 | import cn.enilu.tool.database.doc.generator.bean.ColumnVo; 4 | import cn.enilu.tool.database.doc.generator.bean.DdgDataSource; 5 | import cn.enilu.tool.database.doc.generator.bean.TableVo; 6 | import org.nutz.dao.entity.Record; 7 | import org.nutz.dao.impl.SimpleDataSource; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Oracle 14 | * 15 | * @author zt 16 | * @version 2019/1/6 0006 17 | */ 18 | public class Oracle extends Generator{ 19 | private String sqlTables = "select * from user_tab_comments"; 20 | private String sqlColumns = "select column_name,data_type,data_length,nullable from user_tab_columns where " + 21 | "Table_Name='@tablename'"; 22 | private String sqlColumnComments = "select column_name,comments from user_col_comments where TABLE_NAME='@tablename'"; 23 | public Oracle(String dbName, DdgDataSource dataSource) { 24 | super(dbName, dataSource); 25 | } 26 | 27 | @Override 28 | public List getTableData() { 29 | List list = getList(sqlTables); 30 | List tables = new ArrayList<>(); 31 | for(int i=0;i columns = getList(sql); 47 | List columnComments = getList(sql2); 48 | List columnVoList = new ArrayList<>(); 49 | for(int i=0;i 0 and a.attrelid = c.oid and a.atttypid = t.oid" + 25 | " ORDER BY a.attnum"; 26 | 27 | public PostgreSQL(String dbName, DdgDataSource dataSource) { 28 | super(dbName, dataSource); 29 | } 30 | 31 | @Override 32 | public List getTableData() { 33 | List list = getList(sqlTables); 34 | List tables = new ArrayList<>(); 35 | for(int i=0;i columns = getList(sql); 51 | 52 | List columnVoList = new ArrayList<>(); 53 | for(int i=0;i list) { 40 | Map map = new HashMap(); 41 | map.put("dbName", dbName); 42 | map.put("tables", list); 43 | try { 44 | Template template = configuration.getTemplate(Constants.DB_MONGO == dbType?"database-mongo.html":"database.html"); 45 | String name = dbName + "-doc" + File.separator + dbName + ".html"; 46 | File f = new File(name); 47 | Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8"); 48 | template.process(map, w); 49 | w.close(); 50 | new Html2DocConverter(dbName + "-doc" + File.separator + dbName + ".html", dbName + "-doc" + File 51 | .separator + dbName + ".doc") 52 | .writeWordFile(); 53 | } catch (Exception ex) { 54 | ex.printStackTrace(); 55 | 56 | } 57 | 58 | } 59 | 60 | 61 | public static void main(String[] args) throws Exception { 62 | Map map = new HashMap(); 63 | List list = new ArrayList<>(); 64 | for (int i = 0; i < 5; i++) { 65 | TableVo tableVo = new TableVo(); 66 | tableVo.setTable("表" + i); 67 | tableVo.setComment("注释" + i); 68 | List columns = new ArrayList<>(); 69 | for (int j = 0; j < 5; j++) { 70 | ColumnVo columnVo = new ColumnVo(); 71 | columnVo.setName("name" + j); 72 | columnVo.setComment("注释" + j); 73 | columnVo.setKey("PRI"); 74 | columnVo.setIsNullable("是"); 75 | columnVo.setType("varchar(2"); 76 | columns.add(columnVo); 77 | 78 | } 79 | tableVo.setColumns(columns); 80 | list.add(tableVo); 81 | } 82 | 83 | createDoc(Constants.DB_MYSQL,"test", list); 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/database/MySQL.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator.database; 2 | import cn.enilu.tool.database.doc.generator.bean.ColumnVo; 3 | import cn.enilu.tool.database.doc.generator.bean.DdgDataSource; 4 | import cn.enilu.tool.database.doc.generator.bean.TableVo; 5 | import org.nutz.dao.entity.Record; 6 | import org.nutz.dao.impl.SimpleDataSource; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * DatabaseDocService 13 | * 14 | * @author zt 15 | * @version 2018/10/6 0006 16 | */ 17 | public class MySQL extends Generator { 18 | String sqlTables = "select table_name,table_comment,table_rows,data_length from information_schema.tables where table_schema = '@dbname'" + 19 | " order by table_name asc"; 20 | String sqlColumns = "select column_name,column_type,column_key,is_nullable,column_comment from information_schema" + 21 | ".columns where table_schema = '@dbname' and table_name " + 22 | "='@tablename'"; 23 | 24 | public MySQL(String dbName, DdgDataSource dataSource){ 25 | super(dbName,dataSource); 26 | } 27 | @Override 28 | public List getTableData(){ 29 | String sql = sqlTables.replace("@dbname",dbName); 30 | List list = getList(sql); 31 | List tables = new ArrayList<>(); 32 | for(int i=0;i list =getList(sql); 55 | List columns = new ArrayList<>(); 56 | for(int i=0;i getTableData() { 59 | List list = getList(sqlTables); 60 | List tables = new ArrayList<>(); 61 | for (int i = 0; i < list.size(); i++) { 62 | Record record = list.get(i); 63 | String table = record.getString("name"); 64 | String comment = record.getString("comment"); 65 | TableVo tableVo = getTableInfo(table, comment); 66 | tables.add(tableVo); 67 | } 68 | return tables; 69 | } 70 | 71 | public TableVo getTableInfo(String table,String tableComment){ 72 | TableVo tableVo = new TableVo(); 73 | tableVo.setTable(table); 74 | tableVo.setComment(tableComment); 75 | String sql = sqlColumns.replace("@tablename",table); 76 | List list =getList(sql); 77 | List columns = new ArrayList<>(); 78 | for(int i=0;i getTableData() { 44 | List tables = new ArrayList<>(); 45 | Set collectionNames = zMoDB.cNames(); 46 | Iterator iter = collectionNames.iterator(); 47 | while (iter.hasNext()) { 48 | String collectionname = iter.next(); 49 | ZMoCo zMoCo = zMoDB.c(collectionname); 50 | ZMoDoc doc = zMoCo.findOne(); 51 | TableVo tableVo = getTableInfo(doc, collectionname); 52 | if (tableVo != null) { 53 | tables.add(tableVo); 54 | } 55 | } 56 | 57 | 58 | return tables; 59 | } 60 | 61 | private TableVo getTableInfo(ZMoDoc doc, String tableName) { 62 | TableVo tableVo = new TableVo(); 63 | tableVo.setTable(tableName); 64 | if (doc == null) { 65 | return null; 66 | } 67 | Set keys = doc.keySet(); 68 | Iterator iter = keys.iterator(); 69 | List columns = new ArrayList<>(); 70 | while (iter.hasNext()) { 71 | ColumnVo column = new ColumnVo(); 72 | String key = iter.next(); 73 | column.setName(key); 74 | Object object = doc.get(key); 75 | getColumnInfo(null, key, object, columns); 76 | 77 | } 78 | tableVo.setColumns(columns); 79 | return tableVo; 80 | } 81 | 82 | private void getColumnInfo(String parent, String key, Object object, List columns) { 83 | if (object == null) { 84 | return; 85 | } 86 | if("__v".equalsIgnoreCase(key) || "_class".equalsIgnoreCase(key)){ 87 | return ; 88 | } 89 | 90 | String currentKey = Strings.isNotBlank(parent) ? (parent + "." + key) : key; 91 | 92 | ColumnVo column = new ColumnVo(); 93 | column.setName(currentKey); 94 | columns.add(column); 95 | if (object instanceof String) { 96 | 97 | column.setType("string"); 98 | } else if (object instanceof Integer) { 99 | 100 | column.setType("integer"); 101 | } else if (object instanceof BasicDBList) { 102 | column.setType("list"); 103 | currentKey = key+"[]"; 104 | column.setName(currentKey); 105 | BasicDBList list = (BasicDBList) object; 106 | if (list.size() > 0) { 107 | 108 | Object object2 = list.get(0); 109 | getColumnInfo(currentKey, currentKey, object2, columns); 110 | } else { 111 | columns.remove(column); 112 | } 113 | 114 | } else if (object instanceof BasicDBObject) { 115 | column.setType("object"); 116 | if(parent!=null&&parent.contains("[]")){ 117 | columns.remove(column); 118 | } 119 | 120 | BasicDBObject dbObject = (BasicDBObject) object; 121 | Iterator iter = dbObject.keySet().iterator(); 122 | while (iter.hasNext()) { 123 | String key2 = iter.next(); 124 | if(parent!=null&&parent.contains("[]")){ 125 | getColumnInfo(parent, key2, dbObject.get(key2), columns); 126 | }else { 127 | getColumnInfo(currentKey, key2, dbObject.get(key2), columns); 128 | } 129 | } 130 | } else if (object instanceof Boolean) { 131 | column.setType("boolean"); 132 | } else if (object instanceof Double) { 133 | column.setType("double"); 134 | } else if (object instanceof ObjectId) { 135 | columns.remove(column); 136 | } else if (object instanceof Date) { 137 | column.setType("date"); 138 | } else if (object instanceof Long) { 139 | column.setType("long"); 140 | } else { 141 | column.setType(object.getClass().getName()); 142 | } 143 | 144 | 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/database/Generator.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator.database; 2 | 3 | import cn.enilu.tool.database.doc.generator.bean.ColumnVo; 4 | import cn.enilu.tool.database.doc.generator.bean.Constants; 5 | import cn.enilu.tool.database.doc.generator.bean.DdgDataSource; 6 | import cn.enilu.tool.database.doc.generator.bean.TableVo; 7 | import cn.enilu.tool.database.doc.generator.doc.WordGenerator; 8 | import org.nutz.dao.Dao; 9 | import org.nutz.dao.Sqls; 10 | import org.nutz.dao.entity.Record; 11 | import org.nutz.dao.impl.NutDao; 12 | import org.nutz.dao.impl.SimpleDataSource; 13 | import org.nutz.dao.sql.Sql; 14 | import org.nutz.lang.Files; 15 | import org.nutz.lang.Strings; 16 | 17 | import java.io.File; 18 | import java.util.List; 19 | import java.util.Scanner; 20 | 21 | /** 22 | * Generator 23 | * 24 | * @author zt 25 | * @version 2019/1/6 0006 26 | */ 27 | public abstract class Generator { 28 | private SimpleDataSource dataSource; 29 | private DdgDataSource ddgDataSource; 30 | protected Dao dao = null; 31 | protected String dbName; 32 | protected String docPath; 33 | 34 | public Generator(String dbName, DdgDataSource dataSource) { 35 | this.ddgDataSource = dataSource; 36 | if(Constants.DB_MONGO != dataSource.getDbType()){ 37 | 38 | this.dataSource = dataSource.getDs(); 39 | dao = new NutDao(this.dataSource); 40 | } 41 | this.dbName = dbName; 42 | this.docPath = dbName + "-doc"; 43 | } 44 | 45 | /** 46 | * 获取表结构数据 47 | * 48 | * @return 49 | */ 50 | public abstract List getTableData(); 51 | 52 | public void generateDoc() { 53 | File docDir = new File(docPath); 54 | if (docDir.exists()) { 55 | 56 | String str = "\n【温馨提示】 - 文件夹" + docPath + "已存在。 是否删除?(y 默认删除)\n"; 57 | //throw new RuntimeException(str); 58 | System.out.print(str); 59 | 60 | Scanner sc = new Scanner(System.in); 61 | String dbType = sc.nextLine(); 62 | if ("y".equals(dbType) || "".equals(dbType)) { 63 | docDir.delete(); 64 | } 65 | else 66 | { 67 | return; 68 | } 69 | } else { 70 | docDir.mkdirs(); 71 | } 72 | List list = getTableData(); 73 | save2File(list); 74 | //保存word 75 | WordGenerator.createDoc(ddgDataSource.getDbType(),dbName,list); 76 | 77 | } 78 | 79 | public void save2File(List tables) { 80 | saveSummary(tables); 81 | saveReadme(tables); 82 | for (TableVo tableVo : tables) { 83 | saveTableFile(tableVo); 84 | } 85 | } 86 | 87 | private void saveSummary(List tables) { 88 | StringBuilder builder = new StringBuilder("# Summary").append("\r\n").append("* [Introduction](README.md)") 89 | .append("\r\n"); 90 | for (TableVo tableVo : tables) { 91 | String name = Strings.isEmpty(tableVo.getComment()) ? tableVo.getTable() : tableVo.getComment(); 92 | builder.append("* [" + name + "](" + tableVo.getTable() + ".md)").append("\r\n"); 93 | } 94 | try { 95 | Files.write(new File(docPath + File 96 | .separator + "SUMMARY.md"), builder.toString()); 97 | } catch (Exception e) { 98 | e.printStackTrace(); 99 | } 100 | } 101 | 102 | private void saveReadme(List tables) { 103 | StringBuilder builder = new StringBuilder("# " + dbName + "数据库文档").append("\r\n"); 104 | for (TableVo tableVo : tables) { 105 | builder.append("- [" + (Strings.isEmpty(tableVo.getComment()) ? tableVo.getTable() : tableVo.getComment()) 106 | + "]" + 107 | "(" + tableVo 108 | .getTable() + ".md)") 109 | .append 110 | ("\r\n"); 111 | } 112 | try { 113 | Files.write(new File(docPath + File 114 | .separator + "README.md"), builder.toString()); 115 | } catch (Exception e) { 116 | e.printStackTrace(); 117 | } 118 | } 119 | 120 | private void saveTableFile(TableVo table) { 121 | 122 | StringBuilder builder = new StringBuilder("# " + (Strings.isBlank(table.getComment()) ? table.getTable() : table 123 | .getComment()) + "(" + table.getTable() + ")").append("\r\n"); 124 | builder.append("| 列名 | 类型 | KEY | 可否为空 | 注释 |").append("\r\n"); 125 | builder.append("| ---- | ---- | ---- | ---- | ---- |").append("\r\n"); 126 | List columnVos = table.getColumns(); 127 | for (int i = 0; i < columnVos.size(); i++) { 128 | ColumnVo column = columnVos.get(i); 129 | builder.append("|").append(column.getName()).append("|").append(column.getType()).append("|").append 130 | (Strings.sNull(column.getKey())).append("|").append(column.getIsNullable()).append("|").append 131 | (column.getComment()).append("|\r\n"); 132 | } 133 | try { 134 | Files.write(new File(docPath + File 135 | .separator + table.getTable() + ".md"), builder.toString()); 136 | } catch (Exception e) { 137 | e.printStackTrace(); 138 | } 139 | } 140 | 141 | public List getList(String sqlStr) { 142 | Sql sql = Sqls.create(sqlStr); 143 | sql.setCallback(Sqls.callback.records()); 144 | dao.execute(sql); 145 | List list = sql.getList(Record.class); 146 | return list; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/cn/enilu/tool/database/doc/generator/Main.java: -------------------------------------------------------------------------------- 1 | package cn.enilu.tool.database.doc.generator; 2 | 3 | import cn.enilu.tool.database.doc.generator.bean.Constants; 4 | import cn.enilu.tool.database.doc.generator.bean.DdgDataSource; 5 | import cn.enilu.tool.database.doc.generator.database.*; 6 | import org.nutz.dao.impl.SimpleDataSource; 7 | 8 | import java.util.Scanner; 9 | 10 | /** 11 | * Main 12 | * 13 | * @author zt 14 | * @version 2018/10/6 0006 15 | */ 16 | public class Main { 17 | public static void main(String[] args) { 18 | Scanner sc = new Scanner(System.in); 19 | System.out.print("choose database:\n1:MySQL\n2:Oracle\n3:PostgreSQL\n4:SQLServer\n5:MongoDB\n" + 20 | "Select the appropriate numbers choose database type\n" + 21 | "(Enter 'c' to cancel):\n "); 22 | int dbType = Integer.valueOf(sc.nextLine()); 23 | if ("c".equals(dbType)) { 24 | System.exit(-1); 25 | } 26 | if (Integer.valueOf(dbType) < 1 || Integer.valueOf(dbType) > 5) { 27 | System.out.println("wrong number,will exit"); 28 | System.exit(-1); 29 | } 30 | String serviceName = null; 31 | String dbName = null; 32 | if (Constants.DB_ORACLE == dbType) { 33 | System.out.println("input service name:"); 34 | serviceName = sc.nextLine(); 35 | } else { 36 | System.out.println("input database name:"); 37 | dbName = sc.nextLine(); 38 | } 39 | System.out.println("input host (default 127.0.0.1) :"); 40 | String ip = sc.nextLine(); 41 | if ("".equals(ip)) { 42 | ip = "127.0.0.1"; 43 | } 44 | 45 | System.out.println("input port (default " + getDefaultPort(dbType) + ") :"); 46 | String port = sc.nextLine(); 47 | if ("".equals(port)) { 48 | port = getDefaultPort(dbType); 49 | } 50 | 51 | System.out.println("input username (default " + getDefaultUser(dbType) + ") :"); 52 | String username = sc.nextLine(); 53 | if ("".equals(username)) { 54 | username = getDefaultUser(dbType); 55 | } 56 | 57 | System.out.println("input password (default 123456) :"); 58 | String passowrd = sc.nextLine(); 59 | if ("".equals(passowrd)) { 60 | passowrd = "123456"; 61 | } 62 | 63 | // SimpleDataSource dataSource = new SimpleDataSource(); 64 | // if ("1".equals(dbType)) { 65 | // dataSource.setJdbcUrl("jdbc:mysql://" + ip + ":" + port + "/" + dbName); 66 | // } else if ("2".equals(dbType)) { 67 | // dataSource.setJdbcUrl("jdbc:oracle:thin:@" + ip + ":" + port + ":" + serviceName); 68 | // } else if ("3".equals(dbType)) { 69 | // dataSource.setJdbcUrl("jdbc:postgresql://" + ip + ":" + port + "/" + dbName); 70 | // } else if ("4".equals(dbType)) { 71 | // dataSource.setJdbcUrl("jdbc:sqlserver://" + ip + ":" + port + ";database=" + dbName); 72 | // }else if("5".equalsIgnoreCase(dbType)){ 73 | // 74 | // } 75 | // dataSource.setUsername(username); 76 | // dataSource.setPassword(passowrd); 77 | DdgDataSource dataSource = new DdgDataSource(); 78 | dataSource.setDbType(dbType); 79 | dataSource.setIp(ip); 80 | dataSource.setPort(port); 81 | dataSource.setDbName("2".equals(dbType) ? serviceName : dbName); 82 | dataSource.setUser(username); 83 | dataSource.setPass(passowrd); 84 | Generator generator = null; 85 | switch (dbType) { 86 | case Constants.DB_MYSQL: 87 | generator = new MySQL(dbName, dataSource); 88 | break; 89 | case Constants.DB_ORACLE: 90 | generator = new Oracle(username, dataSource); 91 | break; 92 | case Constants.DB_POSTGRESQL: 93 | generator = new PostgreSQL(dbName, dataSource); 94 | break; 95 | case Constants.DB_SQLSERVER: 96 | generator = new SqlServer(dbName, dataSource); 97 | case Constants.DB_MONGO: 98 | generator = new Mongo(dbName, dataSource); 99 | default: 100 | System.out.println("not support database"); 101 | break; 102 | } 103 | 104 | generator.generateDoc(); 105 | } 106 | 107 | private static String getDefaultPort(int dbType) { 108 | String defaultPort = ""; 109 | 110 | switch (dbType) { 111 | case Constants.DB_MYSQL: { 112 | defaultPort = "3306"; 113 | break; 114 | } 115 | case Constants.DB_ORACLE: { 116 | defaultPort = "1521"; 117 | break; 118 | } 119 | case Constants.DB_POSTGRESQL: { 120 | defaultPort = "5432"; 121 | break; 122 | } 123 | case Constants.DB_SQLSERVER: { 124 | defaultPort = "1433"; 125 | break; 126 | } 127 | case Constants.DB_MONGO: { 128 | defaultPort = "27017"; 129 | break; 130 | } 131 | default: { 132 | defaultPort = "-"; 133 | break; 134 | } 135 | } 136 | 137 | return defaultPort; 138 | } 139 | 140 | private static String getDefaultUser(int dbType) { 141 | String defaultUser = ""; 142 | 143 | switch (dbType) { 144 | case Constants.DB_MYSQL: { 145 | defaultUser = "root"; 146 | break; 147 | } 148 | case Constants.DB_ORACLE: { 149 | defaultUser = "sytem"; 150 | break; 151 | } 152 | case Constants.DB_POSTGRESQL: { 153 | defaultUser = "postgres"; 154 | break; 155 | } 156 | case Constants.DB_SQLSERVER: { 157 | defaultUser = "sa"; 158 | break; 159 | } 160 | default: { 161 | defaultUser = ""; 162 | break; 163 | } 164 | } 165 | 166 | return defaultUser; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.enilu 8 | database-doc-generator 9 | 1.0 10 | 11 | UTF-8 12 | yyyyMMddHHmmss 13 | 1.8 14 | 1.8 15 | UTF-8 16 | true 17 | 18 | 19 | 20 | org.nutz 21 | nutz 22 | 1.r.66 23 | 24 | 25 | mysql 26 | mysql-connector-java 27 | 5.1.24 28 | 29 | 30 | org.postgresql 31 | postgresql 32 | 42.2.5 33 | 34 | 35 | com.oracle 36 | ojdbc14 37 | 10.2.0.4.0 38 | 39 | 40 | com.microsoft.sqlserver 41 | sqljdbc42 42 | 4.0 43 | system 44 | ${project.basedir}/sqljdbc42.jar 45 | 46 | 47 | 48 | org.nutz 49 | nutzmongo 50 | 1.r.60 51 | 52 | 53 | org.freemarker 54 | freemarker 55 | 2.3.28 56 | 57 | 58 | org.apache.poi 59 | poi 60 | 3.12 61 | 62 | 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-compiler-plugin 68 | 3.0 69 | 70 | ${project.build.sourceEncoding} 71 | ${java_source_version} 72 | ${java_target_version} 73 | -Xlint:unchecked 74 | 75 | 76 | 77 | 78 | org.apache.maven.plugins 79 | maven-surefire-plugin 80 | 81 | ${skipTests} 82 | 83 | 84 | 85 | maven-war-plugin 86 | 2.3 87 | 88 | webapp 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-resources-plugin 94 | 2.6 95 | 96 | ${project.build.sourceEncoding} 97 | 98 | 99 | 100 | 101 | org.codehaus.mojo 102 | truezip-maven-plugin 103 | 1.1 104 | 105 | 106 | remove-a-file-in-sub-archive 107 | 108 | remove 109 | 110 | package 111 | 112 | 113 | ${project.basedir}/lib 114 | 115 | *.jar 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | org.apache.maven.plugins 125 | maven-dependency-plugin 126 | 2.8 127 | 128 | 129 | copy-dependencies 130 | package 131 | 132 | copy-dependencies 133 | 134 | 135 | ${project.basedir}/lib 136 | false 137 | true 138 | 139 | 140 | 141 | 142 | 143 | maven-assembly-plugin 144 | 2.4 145 | 146 | false 147 | ${project.artifactId}-${build.timestamp} 148 | 149 | dist.xml 150 | 151 | 152 | 153 | 154 | make-assembly 155 | package 156 | 157 | assembly 158 | 159 | 160 | 161 | 162 | 163 | org.apache.maven.plugins 164 | maven-jar-plugin 165 | 2.6 166 | 167 | 168 | 169 | **/*.properties 170 | 171 | 172 | 173 | 174 | 175 | 176 | --------------------------------------------------------------------------------