使用screw-core一键生成数据库表结构文档
1. 先从“为什么需要表结构文档”说起我相信绝大多数后端开发都有过这样的经历接手一个老项目数据库里几百张表没有文档只能一张张点开表看字段注释。运气好点的表注释和字段注释写得还算完整运气差的字段名是a、b、c类型是varchar(255)你只能靠猜。更别提那些分布在多个库、多个模块里的表想梳理出一份完整的结构说明基本等于手工考古。那时候我用的办法很原始用 Navicat 把每张表的建表语句导出来再手动整理到 Word 或者 Markdown 里。表少还行表一多维护成本直线上升。而且只要数据库结构一改文档就得跟着改改漏一次后面的人就得多踩一次坑。后来我陆续试过用mysqldump导结构、写 SQL 查询information_schema拼文档、用 Swagger 那套注解自动生成接口文档但让后端兼职维护表注释……都各有各的麻烦。直到我遇到了 screw-core。这个工具解决的最大痛点就是它把“数据库表结构”直接变成一份可读、可检索、可分享的文档全程不需要手动敲一个字。它是一个开源的数据库文档生成工具基于 Java 生态支持 MySQL、PostgreSQL、Oracle、SQL Server、SQLite、MariaDB、达梦等主流数据库能把表结构一键导出为 HTML、Word、Markdown 等格式。如果你是后端开发、DBA、或者做课程设计、毕业设计的学生经常需要交付一份数据库设计说明文档那这个工具值得花一下午时间上手。这篇文章我直接用最简单的方式从一个空项目开始跑通一次完整的 screw-core 生成流程顺便把我在实操中踩过的坑和总结的经验都写出来希望能帮你省掉摸索的时间。2. 核心思路与方案选型2.1 为什么选 screw-core而不是手工写或自研脚本先交代一下背景。在我第一次考虑自动化生成表结构文档的时候其实有几个候选方案我简单对比一下你就知道 screw-core 的定位在哪里了。第一种方案是写 SQL 脚本自己去查information_schema.tables、information_schema.columns然后把结果导出成 CSV 或 Excel。这个方案灵活但只适合“一次性”导出因为你需要对付每个数据库系统的元数据表结构差异MySQL、PostgreSQL、Oracle 的information_schema字段都不一样脚本很难做到通用。第二种方案是用数据库客户端自带的导出功能。Navicat 可以导出表结构但一般导出的是 SQL 建表脚本不是人读的说明文档而且格式固定无法定制。第三种方案是像 Swagger 那样手动添加注解。这是最重的方式相当于每个实体类、每个字段都要写注释和文档标记工作量巨大而且容易和数据库实际结构脱节。screw-core 的本质思路完全不同它直接从数据库里读元数据表名、表注释、字段名、字段注释、字段类型、是否主键、是否允许为空、默认值、索引信息等再通过模板引擎渲染成多种格式的文档。这意味着零人工维护只要数据库注释写得好生成出来的文档质量就高。全库覆盖不用考虑漏表、漏字段的问题有多少张表就生成多少张。一次配置多处使用支持 Maven 插件、Java 代码调用、命令行等多种方式可以接入 CI/CD每次发布前自动生成最新文档。所以我的结论是如果你需要的是“数据库表结构的最终说明文档”screw-core 几乎是当前开源生态里最省事的方案没有之一。2.2 核心工作流与前置要求screw-core 的工作流程不复杂核心就四步配置数据源、加载数据库驱动、读取元数据、渲染输出。但要想让生成的文档真正好用我建议你先满足三个前置条件否则后面生成的文档质量会打折扣第一表和字段的注释必须写清楚。screw-core 生成文档时表名旁边会显示表注释字段名旁边会显示字段注释。如果注释缺失整份文档的可读性会大幅下降。很多老项目的表没有注释这种情况我建议先补一轮注释再生成文档因为工具只是把数据库里的信息“搬运”到文档里源头信息不全文档自然好看不了。第二确认驱动版本和数据库版本匹配。这是新手最常遇到的坑。MySQL 5.x 和 MySQL 8.x 的驱动类名、连接 URL 都有差异比如 MySQL 8 以上的驱动类名是com.mysql.cj.jdbc.DriverURL 里还要带上useSSLfalse和serverTimezoneAsia/Shanghai这类参数否则很容易报时区错误或者 SSL 连接异常。后面我会单独列一个避坑清单。第三确定文档输出格式和存放目录。screw-core 支持HTML、Word、Markdown三种主流格式你可以一次生成全部格式也可以只生成其中一种。建议第一次先输出到一个临时目录确认内容没问题后再调整目录和覆盖范围。2.3 直接看效果一份文档大概长什么样在开始写代码之前你先有个心理预期screw-core 生成的 HTML 文档包含一个目录页左侧是表名列表右侧是表的详细字段信息每张表包含表名、表注释、字段名、字段注释、字段类型、是否主键、是否为空、默认值、索引等完整信息。Word 文档和 Markdown 文档的结构类似。这其实就是我们在课程设计、项目验收、团队交接时最喜欢的那类文档——结构完整、信息准确、不用自己排版。我记得我第一次用这工具给我负责的一个老模块生成文档那个模块有 30 多张表手工整理至少要半天用工具生成只花了几分钟那一刻真的有一种“为什么没早点用”的感慨。3. 从零到一快速跑通 screw-core3.1 环境准备这部分假设你手头有一个可以正常连接、里面有数据的数据库。我用的是 MySQL 8.0Java 版本是 JDK 8构建工具用 Maven。screw-core 官方支持 JDK 8所以如果你的项目还在用老 JDK 也没有问题。你需要准备的环境清单组件版本建议说明JDK8screw-core 最低要求 JDK 8Maven3.6用于引入依赖和执行插件MySQL5.7 / 8.0其他数据库也可驱动需额外引入screw-core最新版如 1.0.5Maven 中央仓库可直接拉取MySQL JDBC 驱动8.0.x与 MySQL 数据库版本匹配我这边建议先用 Maven 创建一个最简单的 Java 项目不需要 Spring Boot 全家桶直接一个带main方法的普通 Maven 项目就够了。screw-core 本身不依赖 Spring用纯 Java 代码就能跑起来这样更容易理解它每一步在干什么。3.2 Maven 依赖引入在pom.xml里加入以下依赖dependencies !-- screw-core 核心依赖 -- dependency groupIdcn.smallbun.screw/groupId artifactIdscrew-core/artifactId version1.0.5/version /dependency !-- MySQL 驱动按你实际数据库选择 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency /dependencies注意screw-core 1.0.5 是截至我写这篇文章时比较稳定的版本你可以在 Maven 中央仓库确认最新版本。如果你的项目已经用了 Spring Boot需要注意依赖冲突尤其是 commons-lang3 这类常用库的版本。3.3 最简单的现场生成代码下面是核心代码。我把每个配置项的作用都写在注释里方便你对着看。import cn.smallbun.screw.core.Configuration; import cn.smallbun.screw.core.engine.EngineConfig; import cn.smallbun.screw.core.engine.EngineFileType; import cn.smallbun.screw.core.engine.EngineTemplateType; import cn.smallbun.screw.core.execute.DocumentationExecute; import cn.smallbun.screw.core.process.ProcessConfig; import javax.sql.DataSource; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ScrewDemo { public static void main(String[] args) { // 1. 配置数据源 DataSource dataSource buildDataSource(); // 2. 生成配置 EngineConfig engineConfig EngineConfig.builder() // 生成文件的存放路径 .fileOutputDir(D:/temp/screw) // 是否打开输出目录 .openOutputDir(false) // 生成的文件类型支持 HTML、WORD、MD .fileType(EngineFileType.HTML) // 生成模板这里使用 freemarker .produceType(EngineTemplateType.freemarker) // 自定义生成的文件名 .fileName(数据库表结构文档) .build(); // 3. 指定需要忽略的表按需配置 ListString ignoreTableName Arrays.asList(flyway_schema_history); ListString ignorePrefix new ArrayList(); ListString ignoreSuffix new ArrayList(); ProcessConfig processConfig ProcessConfig.builder() // 忽略指定的表名 .ignoreTableName(ignoreTableName) // 忽略表前缀比如忽略所有以 t_ 开头的表 .ignoreTablePrefix(ignorePrefix) // 忽略表后缀 .ignoreTableSuffix(ignoreSuffix) .build(); // 4. 组装配置 Configuration config Configuration.builder() // 版本号会显示在生成的文档标题里 .version(1.0.0) // 描述信息 .description(订单系统数据库设计文档) // 数据源 .dataSource(dataSource) // 引擎配置 .engineConfig(engineConfig) // 处理配置可忽略表 .produceConfig(processConfig) .build(); // 5. 执行生成 new DocumentationExecute(config).execute(); System.out.println(数据库表结构文档生成完成); } /** * 构建数据源这里直接使用 HikariCPscrew-core 内部已经集成了 HikariCP */ private static DataSource buildDataSource() { // screw-core 提供了一个简单的数据源构建工具类也可以直接使用 HikariConfig cn.smallbun.screw.core.util.HikariConfig hikariConfig new cn.smallbun.screw.core.util.HikariConfig(); hikariConfig.setDriverClassName(com.mysql.cj.jdbc.Driver); hikariConfig.setJdbcUrl(jdbc:mysql://127.0.0.1:3306/your_database?useUnicodetruecharacterEncodingUTF-8useSSLfalseserverTimezoneAsia/Shanghai); hikariConfig.setUsername(root); hikariConfig.setPassword(your_password); hikariConfig.setMaximumPoolSize(10); return new cn.smallbun.screw.core.util.HikariDataSource(hikariConfig); } }这里有一个小知识点screw-core 内部其实已经集成了 HikariCP 连接池所以我们可以直接用它的HikariDataSource来构造数据源不需要再引入额外的依赖。如果你想用自己的数据源比如 Druid也可以只要实现javax.sql.DataSource接口就行。3.4 执行与输出结果直接运行main方法控制台会输出类似下面的日志[main] INFO cn.smallbun.screw.core.execute.DocumentationExecute - 开始生成数据库设计文档 [main] INFO cn.smallbun.screw.core.process.DataTableProcess - 获取表信息已完成共 12 张表 [main] INFO cn.smallbun.screw.core.process.DataTableProcess - 获取列信息已完成 [main] INFO cn.smallbun.screw.core.process.DataTableProcess - 获取索引信息已完成 [main] INFO cn.smallbun.screw.core.engine.AbstractEngine - 文档生成成功文件位置D:/temp/screw/数据库表结构文档.html打开生成出来的 HTML 文件你会看到一个带侧边栏的页面左侧列出所有表名点击表名右侧展示该表的字段列表。每个字段都包含字段名、数据类型、是否主键、是否为空、默认值、注释等信息。如果你选择了 Markdown 格式生成的是.md文件内容就是一张张 Markdown 表格可以直接贴到 Git 仓库的 docs 目录下。我第一次跑通的时候最直观的感受是省时间、省心、还不容易出错。相比之前手动核对字段这个工具等于把“读库”这件事自动化了。4. 进阶玩法与实用配置4.1 一次生成多种格式文档上文的配置里fileType一次只能指定一种格式。如果你既需要 HTML 给团队成员在浏览器里看又要 Markdown 放到 Git 仓库可以稍微改造一下把生成逻辑封装成一个方法循环执行多种格式。public static void generateByType(DataSource dataSource, EngineFileType fileType, String fileName) { EngineConfig engineConfig EngineConfig.builder() .fileOutputDir(D:/temp/screw) .openOutputDir(false) .fileType(fileType) .produceType(EngineTemplateType.freemarker) .fileName(fileName) .build(); Configuration config Configuration.builder() .version(1.0.0) .description(订单系统数据库设计文档) .dataSource(dataSource) .engineConfig(engineConfig) .build(); new DocumentationExecute(config).execute(); } public static void main(String[] args) { DataSource dataSource buildDataSource(); generateByType(dataSource, EngineFileType.HTML, 数据库表结构文档); generateByType(dataSource, EngineFileType.WORD, 数据库表结构文档); generateByType(dataSource, EngineFileType.MD, 数据库表结构文档); }这里有个细节三种格式共用同一个文件名时会生成三份不同后缀的文件不会互相覆盖。我实际用下来推荐在项目日常维护中优先生成 Markdown 格式因为可以直接 diff结构变更一目了然对外交付或评审时用 Word 格式给别人快速浏览时用 HTML 格式。4.2 指定生成范围只看你想看的表有时候一个库里表非常多但这次只想给某个模块生成文档这时可以用ProcessConfig来控制范围。上面例子中用的ignoreTableName是“排除法”如果你希望更精细化还有includeTableName可以只生成指定的表。ProcessConfig processConfig ProcessConfig.builder() // 只生成这两张表其他表忽略 .includeTableName(Arrays.asList(user, order)) .build();注意一点includeTableName和ignoreTableName是互斥的逻辑。如果同时设置了screw-core 的处理规则是先用includeTableName过滤出表集合再用ignoreTableName排除掉不需要的表。实际使用中我建议除非确实需要否则不要同时配置这两个参数否则很容易出现“我明明设置了几张表怎么生成的却少了几张”的困惑。4.3 在 Spring Boot 项目中集成如果你的项目本身就是 Spring Boot那么在已有DataSource的前提下集成更简单。可以在测试类或启动类里直接注入数据源SpringBootTest class ScrewGeneratorTest { Autowired private DataSource dataSource; Test void generateDatabaseDoc() { EngineConfig engineConfig EngineConfig.builder() .fileOutputDir(./docs) .openOutputDir(false) .fileType(EngineFileType.MD) .produceType(EngineTemplateType.freemarker) .fileName(database-doc) .build(); ProcessConfig processConfig ProcessConfig.builder() .ignoreTableName(Arrays.asList(sys_user, sys_role)) .build(); Configuration config Configuration.builder() .version(1.0.0) .description(Spring Boot 项目数据库文档) .dataSource(dataSource) .engineConfig(engineConfig) .produceConfig(processConfig) .build(); new DocumentationExecute(config).execute(); } }这样你在本地跑一下测试方法文档就生成到./docs目录下了。如果要接入 CI/CD可以把这一步放到流水线里每次发布时自动生成并归档到制品库这样团队拿到的永远是最新结构说明。4.4 让文档更好看表注释与字段注释的规范生成文档质量的上限取决于你的注释质量。这里分享几个我踩过坑之后总结的注释规范建议表注释一句话说明这张表的核心用途比如“用户基本信息表”而不是只写“用户表”。如果表是从某个业务模块拆出来的注释里建议加上模块名。字段注释尽可能说明字段的业务含义和取值范围。比如status字段注释可以写成“状态0-禁用1-启用”。这样生成的文档里别人不用翻代码就能理解字段含义。不要过度依赖工具补注释screw-core 不提供反向把注释写回数据库的能力所以源头注释还是要靠开发者在建表/改表时维护好。如果你负责的老项目注释缺失严重可以临时写一个 SQL把information_schema.columns里的字段信息导出来人工批量补一轮注释再更新表。虽然这项工作比较枯燥但从长期维护的角度看投入产出比很高。5. 常见问题与排查心得5.1 时区或 SSL 连接报错这是 MySQL 8 环境下最容易遇到的问题错误信息通常长这样java.sql.SQLException: The server time zone value йʱ is unrecognized...解决方案就是在 JDBC URL 里加上时区参数String url jdbc:mysql://127.0.0.1:3306/your_database?useUnicodetruecharacterEncodingUTF-8useSSLfalseserverTimezoneAsia/Shanghai;useSSLfalse是为了避免本地开发环境下 SSL 握手带来的额外麻烦生产环境如果需要加密连接可以单独配置 SSL 证书但生成文档这种内部工具场景没必要开。5.2 驱动类找不到如果你用的是 MySQL 5.x 的驱动但配置里写的是com.mysql.cj.jdbc.Driver也会报错。反过来MySQL 8 用老的com.mysql.jdbc.Driver同样可能有问题。一个简单的判断方法看你的pom.xml里mysql-connector-java的版本。5.1.x 版本用com.mysql.jdbc.Driver8.0.x 版本用com.mysql.cj.jdbc.Driver。如果你的项目里既有旧又有新建议统一成 8.0.x新版驱动向下兼容 MySQL 5.7 数据库。5.3 生成出来的文档内容是空的生成成功但文档里只有标题没有表格内容最常见的原因是ProcessConfig里设置的忽略规则把所有表都过滤掉了。比如你设置了ignoreTableName包含所有表名或者ignoreTablePrefix设置成空字符串导致匹配异常。排查思路很简单先把ProcessConfig里的规则清空生成一次确认表数量然后再把忽略规则一项一项加回去。screw-core 在日志里会打印获取到的表数量比如获取表信息已完成共 12 张表如果这个数字是 0那基本可以确定是表被过滤规则误伤了。5.4 生成过程卡住不动这种情况多半是数据库连接问题。我遇到过一种典型的场景数据库服务器和本地网络有防火墙限制本地用 Navicat 连接没问题但 screw-core 生成时连接超时因为 HikariCP 默认的连接超时时间比较长看起来就像卡住了。建议在配置 Hikari 数据源时显式设置连接测试相关参数比如hikariConfig.setConnectionTimeout(30000); hikariConfig.setValidationTimeout(5000); hikariConfig.setMaximumPoolSize(5);此外确认你用的数据库账号有权限读取元数据。比如 MySQL 下需要账号对information_schema有查询权限否则 screw-core 会拿到空的表列表。5.5 其他数据库的使用注意screw-core 不只是支持 MySQL。如果你用的是 PostgreSQL、Oracle、SQL Server、SQLite、MariaDB、达梦等基本上只需要替换驱动和 URL 就能跑通。有几个小地方提醒一下PostgreSQL 的驱动类名是org.postgresql.DriverURL 格式是jdbc:postgresql://127.0.0.1:5432/your_database。达梦数据库的驱动类名是dm.jdbc.driver.DmDriverURL 格式是jdbc:dm://127.0.0.1:5236。SQLite 是文件型数据库URL 一般长这样jdbc:sqlite:/path/to/your.db使用起来最简单不需要账号密码。我在实际项目里用 PostgreSQL 和达梦生成过文档除了驱动和 URL其他配置基本不用改兼容性做得还是不错的。6. 生成文档之后的维护心得工具能帮你把“从库到文档”这一半自动化但另一半“让文档保持最新”还需要流程保障。这里分享一个我后来一直在用的做法把文档生成接入到每次数据库变更的收尾阶段。具体来说我会在涉及表结构变更的需求里加一个“文档同步”的任务。数据库变更脚本执行完之后本地跑一下 screw-core生成新的 Markdown 文档提交到 Git 仓库。这样每个版本的表结构变更都能在代码仓库里追溯到。有朋友问我说直接让 CI 每次构建时重新生成一次文档然后自动提交不是更省事吗我试过但不太推荐全自动因为表结构变更往往需要配合人工确认变更说明全自动提交容易出现“文档变了但没人知道变了什么”的尴尬。反而是在 code review 阶段人工触发一次生成顺便在 PR 描述里列出本次文档变更涉及的表这样整个变更链路是清晰可追溯的。再补充一个小技巧如果团队使用 Git每次提交完数据库结构文档后可以在 commit message 里标注清楚涉及的表名比如docs: 更新订单表和支付表结构说明。这样日后想查找某个时间点的表结构直接翻 Git 提交历史就能定位比在数据库里翻 binlog 或者回忆要可靠得多。7. 写在最后的大白话建议说实话screw-core 这个工具本身不复杂我见过不少同事半小时就能跑通。但工具越简单越能暴露出团队在数据库注释规范和文档维护流程上的短板。如果你打算把它引到团队里我的建议是先花点时间把存量表的注释补齐再统一生成一次文档作为基线然后约定后续表结构变更时必须更新注释、同步文档。我自己用下来的体会是这类“一键生成”的工具最大的价值不在于省下那几分钟而在于它让“数据库结构”这件事从某个人的脑子里、某个人的本地文件里变成了团队共享的、版本可控的、始终和真实环境保持一致的一份资产。对课程设计、毕业设计、项目验收来说它更是能直接帮你产出一份结构规范、内容详实的数据库设计文档。最后分享一个可以减少返工的小经验在第一次生成文档前先拿一个小库试跑确认输出格式和内容样式符合预期再去处理核心业务库。这样就算配置有问题影响面也小排查起来更省事。希望这篇文章能帮你顺利跑通 screw-core少踩几个我踩过的坑。

相关新闻

最新新闻

日新闻

周新闻

月新闻