背景

编写数据库详细设计文档时经常因为数据库表过多和字段过多导致耗费大量的时间。本脚本可以自定义sql语句,查出数据库中所有表的表结构,并取需要的字段生成文档。
gitee地址:https://gitee.com/pengmqqq/mysql-to-word

1、前置准备

导入依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- excel工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.51</version>
        </dependency>

操作步骤

以下为main函数相关代码,相关自定义方法详见文章末尾

获取数据库连接
        String driverUrl = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false&serverTimezone=UTC";
        String username = "root";
        String password = "root";
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection(driverUrl, username, password);
获取数据库的需要生成文档的表
        //需要排除的表
        String notGenTables = "'not_gen_table1','not_gen_table1'";
        //按前缀匹配需要排除的表
        String tableNotLike = "'not_gen_%'";
        //获取数据库的表情单
        List<JSONObject> list = getTables(connection,"test",notGenTables,tableNotLike); 
创建文档
//Blank Document
        XWPFDocument document = new XWPFDocument();
        //添加标题
        XWPFParagraph titleParagraph = document.createParagraph();
        //设置段落居中
        titleParagraph.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleParagraphRun = titleParagraph.createRun();
        titleParagraphRun.setText(TITLE);
        titleParagraphRun.setColor("000000");
        titleParagraphRun.setFontSize(20);
生成数据库表清单
        writeSummaryTable(document, list);
生成各个表详细结构
		int i = 1;
        for (JSONObject json : list) {
            List<String[]> tableDetail = getTableDetail(connection,"cyberops", json.getString("name"));
            String remark = json.getString("remark");
            String title = (i++) + ". " + json.getString("name");
            if (remark != null && !remark.isEmpty()) {
                title += "(" + remark + ")";
            }
            writeTable(document, title, tableDetail);
        }
将文件写入磁盘
		//将文件写入磁盘
        String file = BASE_PATH + FILENAME + System.currentTimeMillis() + SUFFIX_DOC;
        FileOutputStream out = new FileOutputStream(new File(file));
        document.write(out);
        out.close();
        System.out.println("文档生成功,文档路径:"+ file);
        connection.close();

工具类(完整代码)

package com.pengmq.mysqltoword.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;


public class GeneratorDataToWordUtil {
    /**
     * 文档标题
     */
    public static final String TITLE = "数据库设计详细说明书";
    /**
     * 输出文档地址
     */
    public static final String BASE_PATH = "D:\\";
    /**
     * 输出文档名称
     */
    public static final String FILENAME = "数据库设计详细说明书";

    public static final String SUFFIX_DOC = ".doc";

    public static void main(String[] args) throws Exception {
        String driverUrl = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false&serverTimezone=UTC";
        String username = "root";
        String password = "root";
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection(driverUrl, username, password);
        //需要排除的表
        String notGenTables = "'not_gen_table1','not_gen_table1'";
        //按前缀匹配需要排除的表
        String tableNotLike = "'not_gen_%'";
        //获取数据库的表情单
        List<JSONObject> list = getTables(connection,"test",notGenTables,tableNotLike);

        //Blank Document
        XWPFDocument document = new XWPFDocument();
        //添加标题
        XWPFParagraph titleParagraph = document.createParagraph();
        //设置段落居中
        titleParagraph.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleParagraphRun = titleParagraph.createRun();
        titleParagraphRun.setText(TITLE);
        titleParagraphRun.setColor("000000");
        titleParagraphRun.setFontSize(20);

        writeSummaryTable(document, list);
        int i = 1;
        for (JSONObject json : list) {
            List<String[]> tableDetail = getTableDetail(connection,"cyberops", json.getString("name"));
            String remark = json.getString("remark");
            String title = (i++) + ". " + json.getString("name");
            if (remark != null && !remark.isEmpty()) {
                title += "(" + remark + ")";
            }
            writeTable(document, title, tableDetail);
        }

        //将文件写入磁盘
        String file = BASE_PATH + FILENAME + System.currentTimeMillis() + SUFFIX_DOC;
        FileOutputStream out = new FileOutputStream(new File(file));
        document.write(out);
        out.close();
        System.out.println("文档生成功,文档路径:"+ file);
        connection.close();
    }

    private static List<JSONObject> getTables(Connection connection,String dataBaseName,String notGenTables,String tableNotLike) throws SQLException{
        List<JSONObject> list = new ArrayList<>();
        StringBuilder sql = new StringBuilder();
        sql.append("select TABLE_NAME,TABLE_COMMENT from information_schema.tables where table_schema= ? ");
        if (null != tableNotLike) {
            sql.append(" AND table_name NOT LIKE ").append(tableNotLike);
        }
        if (null != notGenTables) {
            sql.append(" AND table_name NOT IN (").append(notGenTables).append(")");
        }
        //获取预处理statement
        PreparedStatement preparedStatement = connection.prepareStatement(sql.toString());
        //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
        preparedStatement.setString(1, dataBaseName);
        //向数据库发出sql执行查询,查询出结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        //遍历查询结果集
        while (resultSet.next()) {
            JSONObject j = new JSONObject();
            j.put("name", resultSet.getString("TABLE_NAME"));
            j.put("remark", resultSet.getString("TABLE_COMMENT"));
            list.add(j);
        }

        resultSet.close();
        preparedStatement.close();

        return list;
    }

    private static List<String[]> getTableDetail(Connection connection,String dataBaseName, String tableName) throws SQLException, ClassNotFoundException {
        List<String[]> list = new ArrayList<>();

        //定义sql语句 ?表示占位符
        String sql = "SELECT COLUMN_NAME  , COLUMN_TYPE  ,  COLUMN_DEFAULT  , if(is_nullable='YES','是','否') IS_NULLABLE  ,if(column_key='PRI','是','否' ) COLUMN_KEY,  COLUMN_COMMENT, EXTRA  FROM INFORMATION_SCHEMA.COLUMNS    WHERE  table_schema = ? and table_name = ?  ";
        //获取预处理statement
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
        preparedStatement.setString(1, dataBaseName);
        preparedStatement.setString(2, tableName);
        //向数据库发出sql执行查询,查询出结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        //遍历查询结果集
        while (resultSet.next()) {
            String[] str = new String[4];
            str[0] = resultSet.getString("COLUMN_NAME");
            str[1] = resultSet.getString("COLUMN_TYPE");
            str[2] = resultSet.getString("COLUMN_COMMENT");
            str[3] = resultSet.getString("EXTRA");
            list.add(str);
        }
        resultSet.close();
        preparedStatement.close();
        return list;
    }

    private static void writeSummaryTable(XWPFDocument document, List<JSONObject> tableList) {
        //表格标题
        document.createParagraph().createRun().setText("数据表清单");
        //创建表格
        XWPFTable comTable = document.createTable();
        comTable.setCellMargins(50,50,50,50);
        //列宽自动分割
        CTTblWidth comTableWidth = comTable.getCTTbl().addNewTblPr().addNewTblW();
        comTableWidth.setType(STTblWidth.DXA);
        comTableWidth.setW(BigInteger.valueOf(9072));
        //表格第一行
        XWPFTableRow comTableRowOne = comTable.getRow(0);
        setCellValue(comTableRowOne.getCell(0), "序号", "DCDCDC", true,true);
        setCellValue(comTableRowOne.addNewTableCell(), "表名", "DCDCDC", true,true);
        setCellValue(comTableRowOne.addNewTableCell(), "功能描述", "DCDCDC", true,true);
        for (int i = 0; i < tableList.size(); i++) {
            JSONObject object = tableList.get(i);
            //新增一行
            XWPFTableRow newComTableRow = comTable.createRow();
            setCellValue(newComTableRow.getCell(0), (i + 1) + "", null, true,true);
            setCellValue(newComTableRow.getCell(1), object.getString("name"), null, true,false);
            setCellValue(newComTableRow.getCell(2), object.getString("remark"), null, true,false);
        }
    }

    private static void writeTable(XWPFDocument document, String title, List<String[]> rows) {
        //两个表格之间加个换行
        document.createParagraph().createRun().setText("\r");
        // 标题1,1级大纲
        document.createParagraph().createRun().setText(title);
        //工作经历表格
        XWPFTable comTable = document.createTable(1, 4);
        comTable.setCellMargins(50,50,50,50);

//        //列宽自动分割
        CTTblWidth comTableWidth = comTable.getCTTbl().addNewTblPr().addNewTblW();
        comTableWidth.setType(STTblWidth.DXA);
        comTableWidth.setW(BigInteger.valueOf(9072));
        //表格第一行
        XWPFTableRow comTableRowOne = comTable.getRow(0);
        setCellValue(comTableRowOne.getCell(0), "字段名", "DCDCDC",true,true);
        setCellValue(comTableRowOne.getCell(1), "字段类型", "DCDCDC",true,true);
        setCellValue(comTableRowOne.getCell(2), "数据描述", "DCDCDC",true,true);
        setCellValue(comTableRowOne.getCell(3), "备注", "DCDCDC",true,true);

        for (String[] str : rows) {
            //表格新增一行
            XWPFTableRow newComTableRow = comTable.createRow();
            for (int col = 0; col < str.length; col++) {
                XWPFTableCell cell = newComTableRow.getCell(col);
                boolean isVerCenter = true;
                boolean isHorCenter = false;
                if (col == 1){
                    isHorCenter = true;
                }
                setCellValue(cell, str[col], null, isVerCenter,isHorCenter);
            }
        }
    }

    private static void setCellValue(XWPFTableCell cell, String text, String color, boolean isVerCenter,boolean isHorCenter) {
        cell.setText(text);
        //垂直居中
        if (isVerCenter) {
            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        }
        if (isHorCenter){
            XWPFParagraph paragraph = cell.getParagraphArray(0);
            paragraph.setAlignment(ParagraphAlignment.CENTER);
        }
        if (color == null || color.isEmpty()) {
            CTTc cttc = cell.getCTTc();
            CTTcPr tcPr = cttc.addNewTcPr();
            tcPr.addNewShd().setFill(color);

        }
    }
}

生成效果

在这里插入图片描述

在这里插入图片描述

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐