在项目中经常需要整理数据库表结构文档。一般情况下都是手动整理数据库表结构设计文档,当表结构有变动的时候,随时自己手动维护。数据库表多了之后,手动整理和维护数据库表结构文档的工作量会非常大,非常单调,还非常容易出错。

有没有什么类似 Swagger 那样好用的工具帮助我们自动生成数据库表结构文档呢?答案是:有。

感谢国内能干的工程师开源了一款数据库表结构文档自动生成工具—— Screw

43.1 Screw 项目概述

Screw 的项目地址是 https://github.com/pingfangushi/screw
image.png
下面是作者关于这个开源项目的说明(真是和我们的感觉很像):

在企业级开发中、我们经常会有编写数据库表结构文档的时间付出,从业以来,待过几家企业,关于数据库表结构文档状态:要么没有、要么有、但都是手写、后期运维开发,需要手动进行维护到文档中,很是繁琐、如果忘记一次维护、就会给以后工作造成很多困扰、无形中制造了很多坑留给自己和后人,于是萌生了要自己写一个插件工具的想法

关于名字,想一个太难了,好在我这个聪明的小脑瓜灵感一现,怎么突出它的小,但重要呢?从小就学过雷锋的螺丝钉精神,摘自雷锋日记:虽然是细小的螺丝钉,是个细微的小齿轮,然而如果缺了它,那整个的机器就无法运转了,慢说是缺了它,即使是一枚小螺丝钉没拧紧,一个小齿轮略有破损,也要使机器的运转发生故障的…,感觉自己写的这个工具,很有这意味,虽然很小、但是开发中缺了它还不行,于是便起名为screw(螺丝钉)。

根据作者的说明,Screw 有如下的特点

  • 简洁轻量、设计良好,代码量很少。
  • 支持多数据库。
  • 可生成多种格式文档。
  • 能够灵活扩展。
  • 支持自定义模板。

    43.3 编写代码生成数据库文档

    43.3.1 概要说明

    生成数据库文档的代码逻辑很简单,只需要经过下面 5 步:
  1. 设置数据源
  2. 设置生成文档的参数
  3. 设置文档处理规则
  4. 构造 Screw 配置对象
  5. 执行生成操作

    43.3.2 创建新的工程

    显然,生成数据库文档的过程只和数据源有关,和任何业务应用程序都没有直接的关系。所以最好写一个独立的Spring Boot 项目来处理这个过程。不管怎么样,绝对不要把和生成数据库文档有关的代码放在正式的业务代码中。
    image.png
    这个工程我们可以不选任何依赖,然后生成后手工放入下面的依赖内容
    1. <dependency>
    2. <groupId>cn.smallbun.screw</groupId>
    3. <artifactId>screw-core</artifactId>
    4. <version>1.0.5</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>com.zaxxer</groupId>
    8. <artifactId>HikariCP</artifactId>
    9. <version>5.0.0</version>
    10. </dependency>
    11. <dependency>
    12. <groupId>org.mariadb.jdbc</groupId>
    13. <artifactId>mariadb-java-client</artifactId>
    14. <scope>runtime</scope>
    15. </dependency>
    你可以通过下面的地址在 mvnrepository 查询最新版本
    https://mvnrepository.com/artifact/cn.smallbun.screw/screw-core

我们先准备一个新的类,接下来本节的代码都放到这个类里面

package com.longser.db.doc;

import org.springframework.stereotype.Component;

@Component
public class DocumentMaker {
}

43.3.3 定义配置参数

首先,需要在这个类中定义如下的参数。而写参数的含义很明显,因此这里不做详细的解释。

    String DOCUMENT_VERSION = "1.0.0";
    String DOCUMENT_TITTLE = "数据库设计文档";
    String DOCUMENT_DIRECTORY = "./doc";

    @Value("${spring.datasource.driver-class-name}")
    String driverClassName;

    @Value("${spring.datasource.url}")
    String jdbcUrl;

    @Value("${spring.datasource.username}")
    String jdbcUsername;

    @Value("${spring.datasource.password}")
    String jdbcPassword;

    EngineFileType fileType = EngineFileType.HTML

在这里我们这里指定生成的文件格式为 HTML。除了 HTML 之外,screw 还支持 Word 、Markdown 这两种文件格式。作者不太建议生成 Word 格式而推荐 Markdown 格式。

43.3.4 获取数据库源

首先定义一个生成数据源的方法:

    /**
     * 获取数据库源
     */
    private DataSource getDataSource() {
        //数据源
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName(driverClassName);
        hikariConfig.setJdbcUrl(jdbcUrl);
        hikariConfig.setUsername(jdbcUsername);
        hikariConfig.setPassword(jdbcPassword);
        //设置可以获取tables remarks信息
        hikariConfig.addDataSourceProperty("useInformationSchema", "true");
        hikariConfig.setMinimumIdle(2);
        hikariConfig.setMaximumPoolSize(5);
        return new HikariDataSource(hikariConfig);
    }

43.3.5 设置生成文档的参数

接下来定义一个方法设置各种生成文档的参数,主要是文档的保存路径、文档类型以及文件名:

    /**
     * 获取文件生成配置
     */
    private EngineConfig getEngineConfig() {
        //生成配置
        return EngineConfig.builder()
                //生成文件路径
                .fileOutputDir(DOCUMENT_DIRECTORY)
                //打开目录
                .openOutputDir(true)
                //文件类型
                .fileType(fileType)
                //生成模板实现
                .produceType(EngineTemplateType.freemarker)
                //自定义文件名称
                .fileName("数据库结构文档").build();
    }

如果不配置生成文件路径则会默认也存放在项目的 doc 目录下。

43.3.6 设置文档处理规则

这一步你可以 用方法 designatedTableName 指定只处理哪些表,或者用方法 ignoreTableName 定义忽略处理哪些表。

通常我们是采用忽略一部分的规则:

    /**
     * 获取数据库表的处理配置,可忽略
     */
    private ProcessConfig getProcessConfig() {
        ArrayList<String> ignoreTableName = new ArrayList<>();
        ignoreTableName.add("test_user");
        ignoreTableName.add("test_group");
        ArrayList<String> ignorePrefix = new ArrayList<>();
        ignorePrefix.add("test_");
        ArrayList<String> ignoreSuffix = new ArrayList<>();
        ignoreSuffix.add("_test");
        return ProcessConfig.builder()
                //忽略表名
                .ignoreTableName(ignoreTableName)
                //忽略表前缀
                .ignoreTablePrefix(ignorePrefix)
                //忽略表后缀
                .ignoreTableSuffix(ignoreSuffix)
                .build();
    }

如果你不指定 ProcessConfig 的话,就会按照默认配置来处理全部。

43.3.7 构造 Screw 配置对象

编写一个方法去构造 Screw 配置对象。这里会用到前面定义的参数或者各种配置对象

    private Configuration getScrewConfig(DataSource dataSource, EngineConfig engineConfig, ProcessConfig processConfig) {
        return Configuration.builder()
                //版本
                .version(DOCUMENT_VERSION)
                //描述
                .description(DOCUMENT_TITTLE)
                //数据源
                .dataSource(dataSource)
                //生成配置
                .engineConfig(engineConfig)
                //生成配置
                .produceConfig(processConfig)
                .build();
    }

43.3.8 生成数据库文档

晚上上面的工作以后,接下来把他们连贯起来执行即可:

    public void generateDatabaseDocumentFile() {
        // 1.获取数据源
        DataSource dataSource = getDataSource();
        // 2.设置生成文档的参数
        EngineConfig engineConfig = getEngineConfig();
        // 3. 设置文档处理规则
        ProcessConfig processConfig = getProcessConfig();
        // 4.构造 Screw 配置对象
        Configuration config = getScrewConfig(dataSource, engineConfig, processConfig);
        // 5.执行生成数据库文档
        new DocumentationExecute(config).execute();
    }

43.3.9 定义数据源

删除 application.properties,创建 application.yml,然后把开发项目中的数据源参数复制过来。

43.3.10 调用生成文档

把主应用程序改成如下内容

package com.longser.db.doc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class MakeDatabaseDocumentApplication {


    static DocumentMaker documentMaker;

    @Autowired
    MakeDatabaseDocumentApplication(DocumentMaker dm) {
        documentMaker = dm;
    }

    public static void main(String[] args) {
        SpringApplication.run(MakeDatabaseDocumentApplication.class, args);

        documentMaker.generateDatabaseDocumentFile();
    }
}

运行程序很快就能生成期望的文档。改变 fileType 的赋值,你可以先后得到下面三种不同格式的文档
image.png

下图就是生成的 HTML 格式的数据库设计文档。
image.png

43.4 配置生成数据库文档的插件

除了基于 Java 代码这种方式之外,你还可以通过 screw 提供的 Maven 插件来生成数据库文档。:

43.4.1 编写插件配置

下面是在 pom.xml 中配置插件的片段,你可以看到需要配置的内容与编写代码很相似:

            <plugin>
                <groupId>cn.smallbun.screw</groupId>
                <artifactId>screw-maven-plugin</artifactId>
                <version>1.0.5</version>
                <dependencies>
                    <!-- HikariCP -->
                    <dependency>
                        <groupId>com.zaxxer</groupId>
                        <artifactId>HikariCP</artifactId>
                        <version>5.0.0</version>
                    </dependency>
                    <!--jdbc driver-->
                    <dependency>
                        <groupId>org.mariadb.jdbc</groupId>
                        <artifactId>mariadb-java-client</artifactId>
                        <version>2.7.4</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <!--username-->
                    <username>****</username>
                    <!--password-->
                    <password>****</password>
                    <!--driver-->
                    <driverClassName>org.mariadb.jdbc.Driver</driverClassName>
                    <!--jdbc url-->
                    <jdbcUrl>jdbc:mysql:****</jdbcUrl>
                    <!--生成文件类型-->
                    <fileType>MD</fileType>
                    <!--打开文件输出目录-->
                    <openOutputDir>true</openOutputDir>
                    <!--生成模板-->
                    <produceType>freemarker</produceType>
                    <!--文档名称 为空时:将采用[数据库名称-描述-版本号]作为文档名称-->
                    <fileName>数据库文档</fileName>
                    <!--描述-->
                    <description>数据库设计文档生成</description>
                    <!--版本-->
                    <version>${project.version}</version>
                    <!--标题-->
                    <title>数据库文档</title>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

43.4.2 编写插件配置

打开 Maven 窗口,在 screw 的上下文相关菜单中(或者双击)执行 Build
image.png
如果配置正确,你可以得到类似下面的结果
image.png
只需要 1.668秒 就定生成了我们需要的 Markdown 格式的数据库文档。
image.png

43.5 进一步的讨论

工欲善其事,必先利其器。正如我们在本章开头所说的,手工编写数据库文档是一个效率低下又容易出错的“体力活”。使用 Screw 这样的工具能够极大地提高我们工作的效率。所有有规律的、机械重复的工作都是应该交给计算机去完成

当然,这个 Screw 还有很多可以进一步完善的地方,比如它目前还没有办法帮我们生成关于代码表(数据字典)的文档。但是,根据最新的设计规范,绝大多数的代码(包括行政区划这样的)都应该直接编写在前端,而不是保存在数据库中。所以从这个角度来说,提取代码表的功能并不需要

Screw 提供了编写 Java 代码和配置 Maven 插件两种生成数据库文档的方法。这两种方法都是复制到项目略作修改即可工作。尤其编写 Java 代码的方法,不涉及单独配置数据源参数的内容,用起来更加方案安全。当然,如果有人能够给 Screw 套上一个 Web 界面就更理想了——在页面上填写数据源、选择文档类型后生成数据库文档下载。这样非软件工程师也能完成生成数据库文档的工作了。

版权说明:本文由北京朗思云网科技股份有限公司原创,向互联网开放全部内容但保留所有权力。