工具(十二):Java导出MySQL数据库表结构信息到excel

一、背景
遇到需求:将指定数据库表设计,统一导出到一个Excel中,存档查看。
如果一个一个弄,很复杂,耗时长。
二、写一个工具导出下
废话少絮,上码:
2.1 pom导入
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.4.0</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.4.0</version></dependency>
2.2 工具类
这里提供思路和示例
package com.eduer.books.modules.app.controller;import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.FileOutputStream;
import java.sql.*;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;/*** Java导出mysql数据库表结构信息到excel* @author wangdy* 2025/3/13*/
public class DatabaseExporter {private static final Pattern INVALID_SHEETNAME_CHARS = Pattern.compile("[\\\\/*?\\[\\]:]");private static final int MAX_SHEETNAME_LENGTH = 31;public static void exportToExcel(String dbName, String jdbcUrl, String username, String password, String outputPath)throws Exception {Set<String> usedSheetNames = new HashSet<>();try (Workbook workbook = new XSSFWorkbook(); Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {DatabaseMetaData metaData = conn.getMetaData();ResultSet tables = metaData.getTables(dbName, null, "%", new String[]{"TABLE"});while (tables.next()) {String catalog = tables.getString("TABLE_CAT");String schema = tables.getString("TABLE_SCHEM");String tableName = tables.getString("TABLE_NAME");// 生成合法的Sheet名称String baseSheetName = generateBaseSheetName(catalog, schema, tableName);String uniqueSheetName = generateUniqueSheetName(baseSheetName, usedSheetNames);Sheet sheet = workbook.createSheet(uniqueSheetName);usedSheetNames.add(uniqueSheetName);createHeaderRow(sheet);processTableColumns(metaData, tableName, sheet);autoSizeColumns(sheet, 7);}try (FileOutputStream outputStream = new FileOutputStream(outputPath)) {workbook.write(outputStream);}}}private static String generateBaseSheetName(String catalog, String schema, String tableName) {// 优先使用schema信息,MySQL中一般用catalog表示数据库String prefix = "";if (schema != null && !schema.isEmpty()) {prefix = schema;} else if (catalog != null && !catalog.isEmpty()) {prefix = catalog;}String rawName = prefix.isEmpty()? tableName: prefix + "_" + tableName;// 替换非法字符并格式化return formatSheetName(rawName);}private static String formatSheetName(String rawName) {// 1. 替换非法字符String sanitized = INVALID_SHEETNAME_CHARS.matcher(rawName).replaceAll("_");// 2. 去除首尾特殊字符sanitized = sanitized.replaceAll("^[\\s']+", "").replaceAll("[\\s']+$", "");// 3. 压缩连续下划线sanitized = sanitized.replaceAll("_{2,}", "_");// 4. 截断长度return sanitized.length() > MAX_SHEETNAME_LENGTH? sanitized.substring(0, MAX_SHEETNAME_LENGTH): sanitized;}private static String generateUniqueSheetName(String baseName, Set<String> usedNames) {if (!usedNames.contains(baseName)) {return baseName;}int suffix = 1;String candidateName;do {String suffixStr = "_" + suffix++;int maxBaseLength = MAX_SHEETNAME_LENGTH - suffixStr.length();candidateName = (baseName.length() > maxBaseLength? baseName.substring(0, maxBaseLength): baseName) + suffixStr;} while (usedNames.contains(candidateName));return candidateName;}private static void processTableColumns(DatabaseMetaData metaData, String tableName, Sheet sheet)throws SQLException {ResultSet columns = metaData.getColumns(null, null, tableName, null);Set<String> primaryKeys = getPrimaryKeys(metaData, tableName);int rowNum = 1;while (columns.next()) {Row row = sheet.createRow(rowNum++);fillRowData(columns, primaryKeys, row);}columns.close();}// 以下方法保持不变(createHeaderRow, createHeaderStyle, getPrimaryKeys, fillRowData, autoSizeColumns)private static void createHeaderRow(Sheet sheet) {Row headerRow = sheet.createRow(0);String[] headers = {"字段名称", "字段类型", "长度", "是否主键", "允许空值", "默认值", "字段注释"};CellStyle headerStyle = createHeaderStyle(sheet.getWorkbook());for (int i = 0; i < headers.length; i++) {Cell cell = headerRow.createCell(i);cell.setCellValue(headers[i]);cell.setCellStyle(headerStyle);}}private static CellStyle createHeaderStyle(Workbook workbook) {CellStyle style = workbook.createCellStyle();Font font = workbook.createFont();font.setBold(true);style.setFont(font);style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);return style;}private static Set<String> getPrimaryKeys(DatabaseMetaData metaData, String tableName) throws SQLException {Set<String> primaryKeys = new HashSet<>();ResultSet pkResultSet = metaData.getPrimaryKeys(null, null, tableName);while (pkResultSet.next()) {primaryKeys.add(pkResultSet.getString("COLUMN_NAME"));}pkResultSet.close();return primaryKeys;}private static void fillRowData(ResultSet columns, Set<String> primaryKeys, Row row) throws SQLException {String columnName = columns.getString("COLUMN_NAME");String typeName = columns.getString("TYPE_NAME");int columnSize = columns.getInt("COLUMN_SIZE");String isNullable = columns.getString("IS_NULLABLE");String defaultValue = columns.getString("COLUMN_DEF");String remarks = columns.getString("REMARKS");row.createCell(0).setCellValue(columnName);row.createCell(1).setCellValue(typeName);row.createCell(2).setCellValue(columnSize);row.createCell(3).setCellValue(primaryKeys.contains(columnName) ? "是" : "否");row.createCell(4).setCellValue("YES".equalsIgnoreCase(isNullable) ? "是" : "否");row.createCell(5).setCellValue(defaultValue != null ? defaultValue : "");row.createCell(6).setCellValue(remarks != null ? remarks : "");}private static void autoSizeColumns(Sheet sheet, int columnCount) {for (int i = 0; i < columnCount; i++) {sheet.autoSizeColumn(i);}}public static void main(String[] args) {try {String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/books-service?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";String username = "root";String password = "xxxxxxx";String outputPath = "数据库表结构.xlsx";exportToExcel("books-service", jdbcUrl, username, password, outputPath);System.out.println("导出成功!");} catch (Exception e) {e.printStackTrace();}}
}
main方法运行即可。
三、结果截图:


END
相关文章:
工具(十二):Java导出MySQL数据库表结构信息到excel
一、背景 遇到需求:将指定数据库表设计,统一导出到一个Excel中,存档查看。 如果一个一个弄,很复杂,耗时长。 二、写一个工具导出下 废话少絮,上码: 2.1 pom导入 <dependency><grou…...
如何设计微服务及其设计原则?
微服务架构是一种将大型单体应用拆分成多个小型、自治服务的设计方式,每个服务专注于单一的业务功能。设计微服务时,需要遵循以下原则和最佳实践: 1. 单一职责原则 核心思想: 每个微服务都应该只负责一块独立的业务功能。这使得…...
ACL初级总结
ACL–访问控制列表 1.访问控制 在路由器流量流入或者流出的接口上,匹配流量,然后执行相应动作 permit允许 deny拒绝 2.抓取感兴趣流 3.ACL匹配规则 自上而下逐一匹配,若匹配到了则按照对应规则执行动作,而不再向下继续匹配 思科:ACL列表末尾隐含一条拒绝所有的规则 华为:AC…...
调优案例一:堆空间扩容提升吞吐量实战记录
📝 调优案例一:堆空间扩容提升吞吐量实战记录 🔧 调优策略:堆空间扩容三部曲 # 原配置(30MB堆空间) export CATALINA_OPTS"$CATALINA_OPTS -Xms30m -Xmx30m"# 新配置(扩容至120MB&am…...
C语言 —— 此去经年梦浪荡魂音 - 深入理解指针(卷一)
目录 1. 内存和地址 2. 指针变量和地址 2.1 取地址操作符(&) 2.2 指针变量 2.3 解引用操作符 (*) 3. 指针的解引用 3.1 指针 - 整数 3.2 void* 指针 4. const修饰指针 4.1 const修饰变量 4.2 const修饰指针变量 5…...
计算机毕业设计:留守儿童的可视化界面
留守儿童的可视化界面mysql数据库创建语句留守儿童的可视化界面oracle数据库创建语句留守儿童的可视化界面sqlserver数据库创建语句留守儿童的可视化界面springspringMVChibernate框架对象(javaBean,pojo)设计留守儿童的可视化界面springspringMVCmybatis框架对象(javaBean,poj…...
golang算法二叉树对称平衡右视图
100. 相同的树 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p [1,2,3], q [1,2,3] 输出:…...
c++20 Concepts的简写形式与requires 从句形式
c20 Concepts的简写形式与requires 从句形式 原始写法(简写形式)等效写法(requires 从句形式)关键区别说明:组合多个约束的示例:两种形式的编译结果:更复杂的约束示例:标准库风格的约…...
Chatbox通过百炼调用DeepSeek
解决方案链接:评测|零门槛,即刻拥有DeepSeek-R1满血版 方案概览 本方案以 DeepSeek-R1 满血版为例进行演示,通过百炼模型服务进行 DeepSeek 开源模型调用,可以根据实际需求选择其他参数规模的 DeepSeek 模型。百炼平台…...
【数据结构】6栈
0 章节 3.1到3.3小节。 认知与理解栈结构; 列举栈的操作特点。 理解并列举栈的应用案例。 重点 栈的特点与实现; 难点 栈的灵活实现与应用 作业或思考题 完成学习测试2,? 内容达成以下标准(考核…...
PyTorch 入门学习
目录 PyTorch 定义 核心作用 应用场景 Pytorch 基本语法 1. 张量的创建 2. 张量的类型转换 3. 张量数值计算 4. 张量运算函数 5. 张量索引操作 6. 张量形状操作 7. 张量拼接操作 8. 自动微分模块 9. 案例-线性回归案例 PyTorch 定义 PyTorch 是一个基于 Python 深…...
mov格式视频如何转换mp4?
mov格式视频如何转换mp4?在日常的视频处理中,经常需要将MOV格式的视频转换为MP4格式,以兼容更多的播放设备和平台。下面给大家分享如何将MOV视频转换为MP4,4款视频格式转换工具分享。 一、牛学长转码大师 牛学长转码大师是一款功…...
数据结构与算法:动态规划dp:子序列相关力扣题(下):392. 判断子序列、115.不同的子序列
392. 判断子序列 1.套最长公共子序列问题的板子 class Solution:def isSubsequence(self, s: str, t: str) -> bool:"""最长公共子序列长度是否len(s),是就是true,否就是falsedp[i][j]考虑以s[i-1],t[j-1]的最长公共子序…...
二进制求和(js实现,LeetCode:67)
这道题我的解决思路是先将a和b的长度保持一致以方便后续按位加减 let lena a.length let lenb b.length if (lena ! lenb) {if (lena > lenb) {for (let i 0; i <lena-lenb; i) {b 0 b}} else {for (let i 0; i < lenb-lena; i) {a 0 a}} } 下一步直接进行按…...
【C#】使用DeepSeek帮助评估数据库性能问题,C# 使用定时任务,每隔一分钟移除一次表,再重新创建表,和往新创建的表追加5万多条记录
🌹欢迎来到《小5讲堂》🌹 🌹这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解。🌹 🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!&#…...
【openGauss】物理备份恢复
文章目录 1. gs_backup(1)备份(2)恢复(3)手动恢复的办法 2. gs_basebackup(1)备份(2)恢复① 伪造数据目录丢失② 恢复 3. gs_probackup(1…...
蓝桥杯备赛-基础练习 day1
1、闰年判断 问题描述 给定一个年份,判断这一年是不是闰年。 当以下情况之一满足时,这一年是闰年:1.年份是4的倍数而不是100的倍数 2.年份是400的倍数。 其他的年份都不是闰年。 输入格式 输入包含一个…...
实验四 Python聚类决策树训练与预测 基于神经网络的MNIST手写体识别
一、实验目的 Python聚类决策树训练与预测: 1、掌握决策树的基本原理并理解监督学习的基本思想。 2、掌握Python实现决策树的方法。 基于神经网络的MNIST手写体识别: 1、学习导入和使用Tensorflow。 2、理解学习神经网络的基本原理。 3、学习使用…...
【原创】在高性能服务器上,使用受限用户运行Nginx,充当反向代理服务器[未完待续]
起因 在公共高性能服务器上运行OllamaDeepSeek,如果按照默认配置启动Ollama程序,则自己在远程无法连接你启动的Ollama服务。 如果修改配置,则会遇到你的Ollama被他人完全控制的安全风险。 不过,我们可以使用一个方向代理&#…...
网络_面试_HTTP请求报文和HTTP响应报文
简介: HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的。HTTP有两类报文:请求报文和响应报文。 HTTP请求报文 一个HTTP请求报文由请求行(request line)、请求头部&…...
详解CPU的组成与功能
CPU的组成与功能 一、 控制单元(Control Unit, CU)二、 算术逻辑单元(Arithmetic Logic Unit, ALU)三、 寄存器(Registers)四、 高速缓存(Cache)五、 辅助结构与技术译码器ÿ…...
Spring boot3-WebClient远程调用非阻塞、响应式HTTP客户端
来吧,会用就行具体理论不讨论 1、首先pom.xml引入webflux依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId> </dependency> 别问为什么因为是响应式....…...
18 | 实现简洁架构的 Handler 层
提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入 云原生 AI 实战 星球,12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra);本节课最终…...
《Transformer如何进行图像分类:从新手到入门》
引言 如果你对人工智能(AI)或深度学习(Deep Learning)感兴趣,可能听说过“Transformer”这个词。它最初在自然语言处理(NLP)领域大放异彩,比如在翻译、聊天机器人和文本生成中表现出…...
coding ability 展开第三幕(滑动指针——基础篇)超详细!!!!
文章目录 前言滑动窗口长度最小的子数组思路 无重复字符的最长子串思路 最大连续1的个数思路 将x减到0的最小操作数思路 总结 前言 前面我们已经把双指针的一些习题练习的差不多啦 今天我们来学习新的算法知识——滑动窗口 让我们一起来探索滑动窗口的魅力吧 滑动窗口 滑动窗口…...
RAGFlow版本升级-Win10系统Docker
下载源码压缩包 https://github.com/infiniflow/ragflow.git 删除旧版本代码文件夹,把下载的代码解压到原先目录 更新一下env文件:ragflow/docker/.env 把值改为最新版本即可 RAGFLOW_IMAGEinfiniflow/ragflow:v0.17.1 更新一下docker docker compose -…...
通过mybatis的拦截器对SQL进行打标
1、背景 在我们开发的过程中,一般需要编写各种SQL语句,万一生产环境出现了慢查询,那么我们如何快速定位到底是程序中的那个SQL出现的问题呢? 2、解决方案 如果我们的数据访问层使用的是mybatis的话,那么我们可以通过…...
如何自己做奶茶,从此告别奶茶店
自制大白兔奶茶,奶香与茶香激情碰撞,每一口都是香浓与甜蜜的双重诱惑,好喝到跺脚!丝滑口感在舌尖舞动,仿佛味蕾在开派对。 简单几步就能复刻,成本超低,轻松在家享受奶茶自由。 材料:大白兔奶糖&…...
JavaScript性能优化实战指南
JavaScript性能优化实战指南 1. 性能分析工具与指标 核心工具链 Chrome DevTools: Performance面板:记录运行时性能,分析长任务(Long Tasks)、强制回流(Layout Shifts)、函数调用堆栈。Memory面…...
宇树人形机器人开源模型
1. 下载源码 https://github.com/unitreerobotics/unitree_ros.git2. 启动Gazebo roslaunch h1_description gazebo.launch3. 仿真效果 H1 GO2 B2 Laikago Z1 4. VMware: vmw_ioctl_command error Invalid argument 这个错误通常出现在虚拟机环境中运行需要OpenGL支持的应用…...
