1. 为什么需要数据库文档生成工具
在日常开发中,数据库设计文档是项目不可或缺的一部分。传统的手动编写方式存在几个明显痛点:
- 文档与数据库实际结构容易脱节,维护成本高
- 表结构变更后需要同步更新文档,容易遗漏
- 多人协作时文档版本混乱,难以保证一致性
我经历过一个电商项目,因为数据库文档没有及时更新,导致新成员花了三天时间才理清各表关系。这正是我开始寻找自动化文档工具的原因。
Screw作为一款轻量级Java库,完美解决了这些问题。它通过JDBC直接连接数据库,实时读取元数据生成文档,确保文档与数据库严格同步。与其他工具相比,Screw有三个突出优势:
- 零学习成本:纯Java实现,与现有项目无缝集成
- 灵活输出:支持Word、HTML、Markdown等多种格式
- 精细控制:可以按表名、前缀、后缀过滤需要生成的表
2. 环境准备与依赖配置
2.1 项目基础环境
确保你的开发环境满足以下条件:
- JDK 1.8+
- Maven 3.5+
- IntelliJ IDEA(2020.3及以上版本推荐)
- MySQL 5.7+/MariaDB(其他数据库需更换驱动)
提示:虽然示例使用MySQL,但Screw支持所有提供JDBC驱动的数据库,包括Oracle、PostgreSQL等,只需更换对应驱动即可。
2.2 Maven依赖配置
在pom.xml中添加以下依赖(以MySQL为例):
xml复制<!-- 数据库驱动必须与你的数据库版本匹配 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<scope>runtime</scope>
</dependency>
<!-- Screw核心库 -->
<dependency>
<groupId>cn.smallbun.screw</groupId>
<artifactId>screw-core</artifactId>
<version>1.0.5</version>
</dependency>
<!-- HikariCP连接池(Screw依赖) -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<!-- Freemarker模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
常见问题排查:
- 如果出现
ClassNotFoundException,检查是否遗漏HikariCP依赖 - 版本冲突时,建议使用dependencyManagement统一管理版本
- 生产环境建议将驱动scope设为runtime,避免编译期依赖
3. 核心代码实现详解
3.1 数据源配置技巧
java复制HikariConfig hikariConfig = new HikariConfig();
// 必须使用cj驱动(MySQL 8.0+)
hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/your_db?useSSL=false&serverTimezone=UTC");
hikariConfig.setUsername("root");
hikariConfig.setPassword("your_password");
// 关键配置:获取表注释必须开启
hikariConfig.addDataSourceProperty("useInformationSchema", "true");
// 连接池优化配置(根据实际场景调整)
hikariConfig.setMinimumIdle(2);
hikariConfig.setMaximumPoolSize(5);
hikariConfig.setConnectionTimeout(30000);
hikariConfig.setIdleTimeout(600000);
hikariConfig.setMaxLifetime(1800000);
DataSource dataSource = new HikariDataSource(hikariConfig);
注意:MySQL 8.0+必须使用cj驱动,否则会报时区错误。url中添加
serverTimezone=UTC可避免时区问题。
3.2 生成配置精讲
java复制EngineConfig engineConfig = EngineConfig.builder()
// 输出目录(建议使用相对路径)
.fileOutputDir(System.getProperty("user.dir") + "/docs")
// 生成后自动打开目录
.openOutputDir(true)
// 支持的文件类型:WORD/HTML/MARKDOWN
.fileType(EngineFileType.WORD)
// 模板引擎(一般不需修改)
.produceType(EngineTemplateType.freemarker)
// 自定义文件名(不带后缀)
.fileName("数据库设计文档_V1.0")
.build();
实际项目中建议:
- 将输出目录设为项目下的docs文件夹
- 文件名包含版本号和日期(如
DB_Doc_20240520) - 团队协作时建议生成HTML格式,便于共享查看
3.3 表过滤策略
java复制// 需要忽略的表名列表
List<String> ignoreTables = Arrays.asList("test_temp", "batch_job_log");
// 忽略前缀(常用于多租户场景)
List<String> ignorePrefix = Arrays.asList("tmp_", "bak_");
// 忽略后缀(常用于备份表)
List<String> ignoreSuffix = Arrays.asList("_history", "_archive");
ProcessConfig processConfig = ProcessConfig.builder()
// 指定生成特定表(空列表表示全部生成)
.designatedTableName(Collections.emptyList())
// 指定生成特定前缀的表
.designatedTablePrefix(Collections.emptyList())
// 指定生成特定后缀的表
.designatedTableSuffix(Collections.emptyList())
// 应用忽略规则
.ignoreTableName(ignoreTables)
.ignoreTablePrefix(ignorePrefix)
.ignoreTableSuffix(ignoreSuffix)
.build();
过滤策略应用场景:
- 开发环境:忽略测试表和备份表
- CI/CD流程:只生成业务核心表
- 文档归档:排除临时表和日志表
4. 高级应用与优化
4.1 文档内容定制
通过继承AbstractTemplateExecute可以完全自定义文档模板:
java复制Configuration config = Configuration.builder()
// 添加自定义描述
.description("这是项目核心业务数据库\n生成时间:" + LocalDateTime.now())
// 添加组织信息
.organization("技术研发部")
// 版本控制
.version("1.0.0")
// 其他配置...
.build();
4.2 与Maven插件集成
在pom.xml中添加build配置,可在打包时自动生成文档:
xml复制<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.your.package.DatabaseDesignDocUtil</mainClass>
</configuration>
</plugin>
</plugins>
</build>
执行命令:
bash复制mvn compile
4.3 文档国际化支持
创建i18n目录,添加如messages_zh_CN.properties:
properties复制screw.title=数据库设计文档
screw.table=表名
screw.column=列名
screw.type=类型
然后在配置中指定:
java复制EngineConfig engineConfig = EngineConfig.builder()
.i18n("i18n/messages_zh_CN")
// 其他配置...
.build();
5. 常见问题解决方案
5.1 表注释不显示问题
现象:生成的文档中表注释为空
解决方法:
- 确认数据库表确实有注释(
SHOW TABLE STATUS) - 检查连接配置是否包含
useInformationSchema=true - MySQL用户需要有
SHOW VIEW权限
5.2 大库生成性能优化
当数据库有数百张表时:
- 增加连接池大小:
java复制hikariConfig.setMaximumPoolSize(20); - 分批生成:
java复制// 每次处理50张表 .designatedTableName(getTablesByBatch(50)) - 使用HTML代替Word(速度快3-5倍)
5.3 字段类型映射异常
现象:数据库的datetime显示为java.sql.Timestamp
解决方案:
java复制ProcessConfig processConfig = ProcessConfig.builder()
.typeMap(Collections.singletonMap("datetime", "日期时间"))
// 其他配置...
.build();
6. 生产环境最佳实践
-
权限控制:
- 创建专用只读账号
- 限制仅能访问information_schema和业务库
-
文档归档:
java复制.fileOutputDir("/nas/db-docs/"+LocalDate.now()) -
邮件通知:
java复制if(EngineFileType.HTML.equals(fileType)){ sendEmail("数据库文档已更新", "查看地址:file://"+path); } -
版本对比:
使用Git管理文档目录,可以直观看到表结构变更历史 -
敏感信息处理:
java复制.ignoreTableName(Arrays.asList("user_password", "payment_info"))
我在金融项目中实施这套方案后,数据库文档维护时间从每周2人天降到了0.5人天,且再未出现过文档与数据库不一致的情况。特别是在审计时,能够快速提供准确的结构变更记录,极大提升了团队效率。