Java实现数据库表结构导出为Word文档

244 阅读2分钟

声明

本文章为纯原创,若需转载烦请备注来源。里面涉及到的代码仅供学习使用。

需求

甲方要求我们提供一份数据库设计文档,需要把所有的表结构罗列上去。项目目前涉及到表大概200+个,手工写word肯定是比较耗费时间的。找了下资源也有工具能做到,比如navicat mysql版,但是手头上没有这款工具,简单的找了找POI文档,决定自己手写一个导出Word程序。实现过程还是比较简单的,大家一起来看看。

基本环境

  1. jdk 1.8
  2. Apache poi 4.1.2

image.png

输出效果

(本人比较懒,直接使用项目库,所以有些打码,忘理解😃。 文档还是比较简陋,以此为基准稿也能减省不少时间🐝) 文档首页

正文

实现代码

1. 完整代码

(平台不能粘贴完整代码,故分两部分:主要代码和完整结构截图)

public static void main(String[] args) throws IOException {
    exportDbSchema();
}

public static void exportDbSchema() throws IOException {
    Map<String, String> tables = getTables();
    List<ColumnModel> columns = getColumns();

    try (XWPFDocument doc = new XWPFDocument()) {
        XWPFParagraph p = doc.createParagraph();
        p.setAlignment(ParagraphAlignment.CENTER);

        XWPFRun r = p.createRun();
        r.setText("数据库设计");
        r.setBold(true);
        r.setFontFamily("黑体");
        r.setFontSize(18);

        p.createRun().addBreak(BreakType.PAGE);

        writeSchema(tables, columns, doc);

        try (OutputStream os = Files.newOutputStream(new File("数据库设计.docx").toPath())) {
            doc.write(os);
        }

    }
}

private static void writeSchema(Map<String, String> tables, List<ColumnModel> columns, XWPFDocument doc) {
    ArrayList<Map.Entry<String, String>> entries = new ArrayList<>(tables.entrySet());
    entries.sort(Map.Entry.comparingByKey());

    Map<String, List<ColumnModel>> columnMap = columns.stream().collect(Collectors.groupingBy(ColumnModel::getTable));

    XWPFParagraph p;
    XWPFRun r;
    int index = 1;
    for (Map.Entry<String, String> table : entries) {
        p = doc.createParagraph();
        p.setAlignment(ParagraphAlignment.LEFT);
        p.setWordWrapped(true);
        p.getCTP().getPPr().addNewOutlineLvl().setVal(new BigInteger("1"));

        r = p.createRun();
        CTFonts ctFonts = r.getCTR().addNewRPr().addNewRFonts();
        ctFonts.setAscii("Times New Roman");
        ctFonts.setEastAsia("宋体");
        r.setFontSize(10);

        r.setText(String.format("%d. %s", index, table.getKey()));
        r.setFontFamily("黑体");
        r.setStyle("3");

        if (StringUtils.isNotBlank(table.getValue())) {
            p = doc.createParagraph();
            r = p.createRun();
            ctFonts = r.getCTR().addNewRPr().addNewRFonts();
            ctFonts.setAscii("Times New Roman");
            ctFonts.setEastAsia("宋体");
            r.setFontSize(10);
            r.setText(table.getValue());
        }

        List<ColumnModel> list = columnMap.get(table.getKey());
        writeColumn(list, doc);

        index += 1;
    }

}

private static void writeColumn(List<ColumnModel> list, XWPFDocument doc) {
    String[] headerTitle = new String[]{"名称","数据类型","是否主键","是否为空","注释"};
    String[] width = new String[]{"20%","15%","15%","15%","35%"};

    XWPFTable table = doc.createTable(list.size() + 1, 5);
    table.setWidth("100%");

    List<XWPFTableRow> rows = table.getRows();
    XWPFTableRow header = rows.get(0);
    header.setHeight(50);
    for (int i = 0; i < headerTitle.length; i++) {
        XWPFTableCell cell = header.getCell(i);
        cell.setWidth(width[i]);
        cell.setText(headerTitle[i]);
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
	}

    for (int i = 0; i < list.size(); i++) {
        ColumnModel col = list.get(i);
        XWPFTableRow row = rows.get(i + 1);
        XWPFTableCell cell = row.getCell(0);
        cell.setWidth(width[0]);
        cell.setText(col.getName());
        XWPFTableCell cell1 = row.getCell(1);
        cell1.setWidth(width[1]);
        cell1.setText(col.getType());
        XWPFTableCell cell2 = row.getCell(2);
        cell2.setWidth(width[2]);
        cell2.setText(col.getPri());
        XWPFTableCell cell3 = row.getCell(3);
        cell3.setWidth(width[3]);
        cell3.setText(col.getNullable());
        XWPFTableCell cell4 = row.getCell(4);
        cell4.setWidth(width[4]);
        cell4.setText(col.getComment());
	}

    XWPFParagraph p = doc.createParagraph();
    p.createRun().addBreak(BreakType.TEXT_WRAPPING);
    p.createRun().addBreak(BreakType.TEXT_WRAPPING);

}

// 表名及表备注结构 可以直接查库
private static Map<String, String> getTables() throws IOException {
    List<String> lines = IOUtils.readLines(Files.newInputStream(new File("tables.json").toPath()), StandardCharsets.UTF_8);
    return JSON.parseObject(StringUtils.join(lines, ""), new TypeReference<Map<String, String>>(){});
}

// 列信息 可以直接查库
private static List<ColumnModel> getColumns() throws IOException {
    List<String> lines = IOUtils.readLines(Files.newInputStream(new File("columns.json").toPath()), StandardCharsets.UTF_8);
    return JSON.parseArray(StringUtils.join(lines, ""), ColumnModel.class);
}

image.png

2. 简单介绍

循环表集合来依次输出具体表信息,一张表一个段落。为了减省运行调试时间,这里将表结构和列信息用json格式保存到文件中。
XWPFDocument.createParagraph()函数创建段落,XWPFDocument.createTable()在word中绘制表格。代码中简单的设置了字体样式、对齐方式、目录设置,若需要调整字体、样式等就需要翻翻poi文档了。(资源比较少,查找还是比较费劲🤯)

3. 数据结构及表信息查询

  • MySQL中查询表及备注信息
    select table_name, table_comment from information_schema.tables where table_schema = 'test' order by table_name
  • MySQL中查询列信息
    select table_name, column_name '名称', column_type '数据类型', column_key '是否主键', is_nullable '是否为空', column_comment '注释' from information_schema.columns where table_schema = 'test' order by table_name, ordinal_position
  • 代码中ColumnModel定义
    image.png