MySQL---数据库从入门走向大神系列(十一)-Java获取数据库/结果集的元信息、将数据表写入excel表格

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 数据库的元信息:首先介绍一下数据库的元信息(元数据):元数据(Metadata)是关于数据的数据。元数据是描述数据仓库内数据的结构和建立方法的数据。存储的数据是什么类型,什么驱动等等,这些描述数据的数据,就是元数据!准备:package cn.

数据库的元信息:

首先介绍一下数据库的元信息(元数据):

元数据(Metadata)是关于数据的数据。

元数据是描述数据仓库内数据的结构和建立方法的数据。

存储的数据是什么类型,什么驱动等等,这些描述数据的数据,就是元数据!

准备:

package cn.hncu.pool3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class ConnsUtil {
    private static List<Connection> pool = new ArrayList<Connection>();
    private static final int NUM=3;
    static{
        try {
            //读取配置文件
            Properties p = new Properties();
            p.load(ConnsUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));
            String driver = p.getProperty("driver");
            String url = p.getProperty("url");
            String user = p.getProperty("username");
            String password = p.getProperty("password");
            Class.forName(driver);

            for(int i=0;i<NUM;i++){
                final Connection conn = DriverManager.getConnection(url, user, password);

                //只需要改这里就行了!
                //使用动态代理代理conn对象,实现对close方法的拦截
                Object obj = Proxy.newProxyInstance(
                        ConnsUtil.class.getClassLoader(),
                        conn.getClass().getInterfaces(),
                        new InvocationHandler() {

                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args)
                                    throws Throwable {
                                if(method.getName().equalsIgnoreCase("close") && (args==null || args.length==0)){
                                    pool.add((Connection)proxy);
                                    return null;
                                }else{
                                    return method.invoke(conn, args);
                                }
                            }
                        });
                pool.add((Connection)obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static synchronized Connection getConn() throws Exception{
        if(pool.size()<=0){
            Thread.sleep(100);
            return getConn();
        }
        return pool.remove(0);
    }

}

使用java.sql 中的接口 DatabaseMetaData就可以实现:

演示类:

package cn.hncu.meta;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;

import org.junit.Test;

import cn.hncu.pool3.ConnsUtil;

public class MetaDataDemo {
    // ※元信息1:通过con获得DatabaseMetaData(数据库元信息)---数据库连接信息、数据库名、表名
    @Test
    public void databaseMetadataDemo() throws Exception {
        // 获取数据库的元信息
        Connection con = ConnsUtil.getConn();
        // ********关键
        DatabaseMetaData dm = con.getMetaData();

        // 获取此 JDBC 驱动程序的名称。
        System.out.println(dm.getDriverName());
        // 获取此 JDBC 驱动程序的主版本号。
        System.out.println(dm.getDriverMajorVersion());
        // 获取在此数据库中在同一时间内可处于开放状态的最大活动语句数。--返回结果为零意味着没有限制或限制是未知的
        System.out.println(dm.getMaxStatements());
        // 获取此驱动程序的主 JDBC 版本号。
        System.out.println(dm.getJDBCMajorVersion());
        // 还有很多方法,可以去API自己查
        System.out.println("=========================");

        // 下面是动态获取数据库名

        ResultSet rs = dm.getCatalogs();
        // 相当于执行:show databases;

        while (rs.next()) {
            System.out.println(rs.getString(1));
            // 进行元数据操作获得数据库名
        }

        // 知道数据库的名字
        con.createStatement().execute("use hncu");
        // 动态获取表名

        // 可以把参数null写成“%o%”进行模糊查询
        ResultSet rs2 = dm.getTables("hncu", "hncu", null,
                new String[] { "TABLE" });

        while (rs2.next()) {
            System.out.println(rs2.getString("TABLE_NAME"));
            // 进行元数据操作,获得表名
        }
    }

    // ※元信息2:通过rs获得ResultSetMetaData(结果集元信息)---表头(每个字段名)、表格行数、列数
    // 在知道数据库名和表名的情况下,把表头和表内容都查询出来。
    @Test
    // 站在结果集的高度---也就是表格
    public void resultSetMetaDataDemo() throws Exception{
        Connection con1 = ConnsUtil.getConn();
        Statement st = con1.createStatement();
        //如果是跨库查询,sql:“数据库名.表名”----select * from 数据库.表名
        String sql = "select * from stud";//我们的连接是hncu数据库的,访问hncu数据库直接写表名就可以
        ResultSet rs = st.executeQuery(sql);

        //结果集的元信息
        ResultSetMetaData rsmd = rs.getMetaData();
        int columns = rsmd.getColumnCount();
        //获得表格的列数

        //输出整个数据表(包括表头)
        //表头
        for(int i=0;i<columns;i++){
            String columnName = rsmd.getColumnName(i+1);
            System.out.print(columnName+"\t");
        }
        System.out.println();
        System.out.println("------------------------");
        //表内容
        while(rs.next()){
            for(int i=0;i<columns;i++){
                String content = rs.getString(i+1);
                System.out.print(content+"\t");
            }
            System.out.println();
        }
    }

}
getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)方法的参数解析:

catalog -类别名称:
它必须与存储在数据库中的类别名称匹配;该参数为 "" 表示获取没有类别的那些描述;为 null则表示该类别名称不应该用于缩小搜索范围 

schemaPattern - 模式名称的模式:
它必须与存储在数据库中的模式名称匹配;该参数为"" 表示获取没有模式的那些描述;为 null 则表示该模式名称不应该用于缩小搜索范围

tableNamePattern -表名称模式:
它必须与存储在数据库中的表名称匹配 

types - 要包括的表类型所组成的列表,必须取自从 getTableTypes()返回的表类型列表;null 表示返回所有类型

这样就遍历出来了。

将数据表写入excel表格

首先需要准备一个apache的Jar:


链接:
https://github.com/chenhaoxiang/Java

先创建一个简单的数据:

package cn.hncu.meta;

import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.Test;

public class ExportXls {

    @Test
    public void mkXlsDemo() throws IOException{
        //需求: 创建一个工作薄:a.xls, 工作表: 表1,  第4行第5列的单元格中写入文字:湖南城院
        HSSFWorkbook book = new HSSFWorkbook();
        HSSFSheet sheet = book.createSheet("表一");

        HSSFRow row4 = sheet.createRow(3);//行数为下标加1
        //该方法的参数值是从0开始的---真正的表格中的序号是从1开始标示

        HSSFCell cell5 = row4.createCell(4);

        FileOutputStream fout = new FileOutputStream("a.xls");
        book.write(fout);
    }
}

将数据库的所有表格数据遍历写入至excel表格

@Test
    public void exportTest() throws Exception{
        //这里我们只遍历存储hncu数据库
        String dbName="hncu";
        String xlsFileName="b.xls";
        exportDb2Xls(dbName,xlsFileName);
    }

    public void exportDb2Xls(String dbName,String xlsFileName) throws Exception{
        HSSFWorkbook book = new HSSFWorkbook();
        Connection con = ConnsUtil.getConn();
        DatabaseMetaData dm = con.getMetaData();

        //写代码时,尽量避免结果集套接操作,在一个结果集操作的内部进行其它结果集操作
        //如果有事务,一个结果集的回退或提交可能会波及另一个
        ResultSet rs = dm.getTables(dbName, dbName, null, new String[]{"TABLE"});

        List<String> tables = new ArrayList<String>();
        while(rs.next()){
            String tableName = rs.getString("TABLE_NAME");
            tables.add(tableName);
        }

        Statement st = con.createStatement();
        for(String tableName: tables){
            //创建一个表名为tableName的表
            HSSFSheet sheet = book.createSheet(tableName);
            //这样写,可以跨数据库访问
            String sql ="select * from "+dbName+"."+tableName;
            rs = st.executeQuery(sql);

            //把表头遍历出来且写到xls文件中
            HSSFRow row = sheet.createRow(0);//表头行
            ResultSetMetaData rsmd = rs.getMetaData();

            int colNum = rsmd.getColumnCount();
            for(int i=0;i<colNum;i++){
                HSSFCell cell = row.createCell(i);
                String colName = rsmd.getColumnName(i+1);
                cell.setCellValue(colName);
            }

            //所有数据行
            int idx = 1;
            while(rs.next()){
                row = sheet.createRow(idx++);
                for(int i=0;i<colNum;i++){
                    HSSFCell cell = row.createCell(i);
                    cell.setCellValue( rs.getString(i+1) );
                }
            }
        }

        FileOutputStream fout = new FileOutputStream(xlsFileName);

        book.write(fout);
    }

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
15天前
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
78 9
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
23天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
52 3
|
23天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
56 3
|
23天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
74 2
|
30天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
1月前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
241 15
|
1月前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
1月前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
2月前
|
关系型数据库 MySQL 数据库
GBase 数据库如何像MYSQL一样存放多行数据
GBase 数据库如何像MYSQL一样存放多行数据
|
2月前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
61 1