JDBC中使用ResultSetMetaData分析结果集


前言

在 Java 中,我们使用 JDBC(Java Database Connectivity)来连接和操作数据库。当我们执行查询语句后,如果事先不知道 ResultSet 里包含哪些数据列,以及每个数据列的数据类型,就可以使用 ResultSetMetaData 对返回的结果集进行解析。那么本文就为大家介绍 ResultSetMetaData 分析结果集。


一、ResultSetMetaData基本介绍

1.ResultSetMetaData介绍

ResultSetMetaData 是 JDBC API 的一部分,在 java.sql 包下,是一个接口。它提供了关于结果集的元数据信息,例如列数、列名、列类型等。通过使用 ResultSetMetaData,我们可以方便地获取结果集的元数据信息,从而更好地解析和处理结果集。

我们来看官方代码说明:

package java.sql;

/**
 * An object that can be used to get information about the types
 * and properties of the columns in a <code>ResultSet</code> object.
 * The following code fragment creates the <code>ResultSet</code> object rs,
 * creates the <code>ResultSetMetaData</code> object rsmd, and uses rsmd
 * to find out how many columns rs has and whether the first column in rs
 * can be used in a <code>WHERE</code> clause.
 * <PRE>
 *
 *     ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM TABLE2");
 *     ResultSetMetaData rsmd = rs.getMetaData();
 *     int numberOfColumns = rsmd.getColumnCount();
 *     boolean b = rsmd.isSearchable(1);
 *
 * </PRE>
 *
 * @since 1.1
 */
public interface ResultSetMetaData extends Wrapper {}

我们从源码可知 ResultSetMetaData 是一个接口,在 java.sql 包下,继承 Wrapper 接口。类注释中说(直译):一个对象,可用于获取关于 ResultSet 对象中列的类型和属性的信息。下面的代码片段创建 ResultSet 对象 rs,创建 ResultSetMetaData 对象 rsmd,并使用 rsmd 来查找 rs 有多少列,以及 rs 中的第一列是否可以用于 WHERE 子句。

我们可以看出 ResultSetMetaData 的用法非常简单,通过 rs.getMetaData() 获取 ResultSetMetaData 对象后,就可以查看分析后的结果。

2.ResultSetMetaData api介绍

世界很大,信息很多,有时候,我们知道某个东西(不精通)更重要。

接下来列出 ResultSetMetaData 常用的一些 API 方法:

// 返回此ResultSet对象中的列数。
int getColumnCount() throws SQLException;
// 指出指定列的正常最大宽度(以字符为单位)。
int getColumnDisplaySize(int column) throws SQLException;
// 获取指定列的建议标题,以用于打印输出和显示。建议的标题通常由SQL AS子句指定。
String getColumnLabel(int column) throws SQLException;
// 获取指定列的名称。
String getColumnName(int column) throws SQLException;
// 获取指定列的表模式。
String getSchemaName(int column) throws SQLException;
// 获取指定列的数据精度。
int getPrecision(int column) throws SQLException;
// 获取指定列在小数点右侧的位数。
int getScale(int column) throws SQLException;
// 获取指定列的表名称。
String getTableName(int column) throws SQLException;
// 获取指定列的表的编目名称。(数据库名)
String getCatalogName(int column) throws SQLException;
// 获取指定列的数据类型。返回的是java.sql.Types中的SQL类型。
int getColumnType(int column) throws SQLException;
// 获取指定列的数据库特定类型名称。
String getColumnTypeName(int column) throws SQLException;
// 返回生成其实例的Java类的全限定名称
String getColumnClassName(int column) throws SQLException;

// 指出指定的列是否为自增编号
boolean isAutoIncrement(int column) throws SQLException;
// 指出指定列是否区分大小写。
boolean isCaseSensitive(int column) throws SQLException;
// 指出指定的列是否可用于where子句。
boolean isSearchable(int column) throws SQLException;
// 指出指定的列是否为货币类型
boolean isCurrency(int column) throws SQLException;
// 指出指定列中值的可空性(该列是否可以为null)
int isNullable(int column) throws SQLException;
// 指出指定列中的值是否为带符号的数字。(该列是否为无符号)
boolean isSigned(int column) throws SQLException;
// 指出指定列是否只读。
boolean isReadOnly(int column) throws SQLException;
// 指出指定列是否可写。
boolean isWritable(int column) throws SQLException;

大家看到上述一些列方法,就很容易明白 ResultSetMetaData 接口是干嘛的了。注意这里的 ResultSetMetaData 接口是 JDBC 提供的标准,具体实现是由各数据库驱动操作的。

二、ResultSetMetaData基本使用

那么接下来我们在实际操作一下,看一下从 ResultSetMetaData 中具体可以获取哪些信息。

import java.sql.*;

public class TestResultSetMetaData {
    public static void main(String[] args) {
        String url = "jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai";
        String user = "root";
        String password = "root";
        String sql = "select * from teacher where id = ?";

        try {
            // 加载数据库驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // 声明数据库连接、预编译语句资源对象
        try (Connection connection = DriverManager.getConnection(url, user, password);
             PreparedStatement preparedStatement = connection.prepareStatement(sql);){

            // 设置参数
            preparedStatement.setInt(1, 1);
            // 执行SQL查询语句,声明ResultSet资源对象
            try(ResultSet resultSet = preparedStatement.executeQuery();) {

                // 通过resultSet.getMetaData()获取该结果集的ResultSetMetaData对象
                ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
                // 获取列数
                int columnCount = resultSetMetaData.getColumnCount();
                System.out.println("查询结果一共有:" + columnCount + "列。");
                // 获取每列的信息,注意列的序列从1开始
                for (int i = 1; i <= columnCount; i++) {
                    System.out.println("===============================第" + i + "列==============================");
                    String columnName = resultSetMetaData.getColumnName(i);
                    int columnType = resultSetMetaData.getColumnType(i);
                    String columnTypeName = resultSetMetaData.getColumnTypeName(i);
                    String columnClassName = resultSetMetaData.getColumnClassName(i);
                    boolean isAutoIncrement = resultSetMetaData.isAutoIncrement(i);
                    
                    System.out.print("=》列名称:" + columnName);
                    System.out.print(",列类型: " + columnType);
                    System.out.print(",列类型名称: " + columnTypeName);
                    System.out.print(",列对应Java类型全限定名: " + columnClassName);
                    System.out.print(",列是否为自增:" + isAutoIncrement);
                    System.out.print(",列是否可为空:" + resultSetMetaData.isNullable(i));
                    System.out.print(",列的最大宽度:" + resultSetMetaData.getColumnDisplaySize(i));
                    System.out.println();
                }

            } catch (SQLException e) {
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

上述代码中,通过 preparedStatement.executeQuery(); 执行预编译好的 SQL,并将查询结果封装在 ResultSet 对象中,接下来调用 ResultSet 对象中的 getMetaData() 方法获取分析后的结果集元数据。然后通过其方法将列名、列类型等获取并打印出来。

三、ResultSetMetaData应用场景

在实际应用中,我们可能需要获取结果集的元数据信息,例如在结果集进行数据转换、数据格式化、数据映射等操作时。通过使用 ResultSetMetaData,我们可以更好地了解结果集的结构和数据类型,从而进行更准确和高效的处理。此外,我们还可以利用 ResultSetMetaData 实现自定义的结果集处理逻辑,例如自定义列名、列宽、格式等。

以下实现一个小功能:连接到 test_jdbc 数据库,展示数据库中各表的表名,用户选择一个表(将表名输入到控制台),然后程序打印出该表的列以及每列的数据。注意以下代码仅仅是一个实现思路,或者说一个小应用场景的展示,并没有考虑过多的代码细节。

import java.sql.*;
import java.util.Scanner;
import java.util.Vector;

public class TestResultSetMetaDataDemo {
    public static void main(String[] args) throws ClassNotFoundException {  
        // 数据库连接信息
        String url = "jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai";
        String user = "root";
        String password = "root";
        // 查询数据库表名信息SQL语句
        String sql = "select table_name from information_schema.tables where table_schema = 'test_jdbc'";

        // 加载数据库驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        // 声明数据库连接、预编译语句资源对象
        try (Connection connection = DriverManager.getConnection(url, user, password);
             PreparedStatement psTable = connection.prepareStatement(sql);){

            // 提示信息
            System.out.println("数据库:test_jdbc");
            System.out.print("该数据库中存在以下表:");
            // 执行查询数据库中表名SQL语句
            try(ResultSet rsTableName = psTable.executeQuery();) {
                // 遍历打印表名
                while (rsTableName.next()){
                    System.out.print(rsTableName.getString("table_name") + "  ");
                }
                System.out.println();// 换行
            }

            // 提示控制台输入表名
            System.out.println("请输入要查询的数据库表:");
            Scanner scanner = new Scanner(System.in);
            String tableName = scanner.nextLine();

            // 预编译并执行查询用户输入表的数据
            try (PreparedStatement psTableData = connection.prepareStatement("select * from " + tableName);
                 ResultSet resultSet = psTableData.executeQuery();){
                // 通过resultSet.getMetaData()获取该结果集的ResultSetMetaData对象
                ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
                // 获取列数
                int columnCount = resultSetMetaData.getColumnCount();
                // 获取每列的信息,注意列的序列从1开始
                for (int i = 1; i <= columnCount; i++) {
                    // 获取列名并打印
                    String columnName = resultSetMetaData.getColumnName(i);
                    System.out.print("  " + columnName + "  ");
                }
                System.out.println();// 换行

                // 将每行数据存储在Vector集合中
                Vector<Vector<String>> rowData = new Vector<>();
                while (resultSet.next()){
                    Vector<String> columnData = new Vector<>();
                    for (int i = 1; i <= columnCount; i++) {
                        columnData.add(resultSet.getString(i));
                    }
                    rowData.add(columnData);
                }

                // 第一层循环遍历每行数据
                for (int i = 0; i < rowData.size(); i++) {
                    Vector<String> columnData = rowData.get(i);
                    // 第二层循环遍历每行中每列数据
                    for (int j = 0; j < columnData.size(); j++) {
                        System.out.print("  " + columnData.get(j) + "  ");
                    }
                    System.out.println();// 换行
                }

            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

运行效果如下:

数据库:test_jdbc
该数据库中存在以下表:teacher  
请输入要查询的数据库表:
teacher
  id    name    sex    age  
  1    张三    男    25  
  2    李四    男    27  
  3    王五    男    28  
  4    赵六    女    20  
  5    张某0    男    20  
  6    张某1    男    20  
  7    张某2    男    20  
  8    张某3    男    20  
  9    张某4    男    20  
  10    张某5    男    20  
  11    张某6    男    20  
  12    张某7    男    20  
  13    张某8    男    20  
  14    张某9    男    20  
  15    张某10    男    20  

以上实现是不是和我们的数据库客户端有点像,只不过我们的程序太简陋。


总结

ResultSetMetaData 是 JDBC 中非常重要的一个接口,它提供了关于结果集的元数据信息。通过使用 ResultSetMetaData,我们可以方便地获取结果集的列数、列名、列类型等,从而更好地解析和处理结果集。在实际应用中,我们可能会遇到不同的数据源和数据类型,通过使用 ResultSetMetaData,我们可以更好地了解和处理这些数据源和数据类型,实现更准确和高效的数据转换、数据格式化、数据映射等操作。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
JDBCJava Database Connectivity)是Java提供的一个进行数据库操作的标准接口。ResultSetJDBC用于表示查询结果的接口,而ResultSetMetaData是用于描述ResultSet的结果元数据的接口。 封装是面向对象编程的一种重要原则,它将数据与操作数据的代码进行了隔离和封装,提高了代码的可维护性和可重用性。在JDBCResultSetResultSetMetaData的封装使得我们可以方便地获取和操作数据库查询的结果。 ResultSet可以通过执行SQL查询语句并将查询结果返回来创建。它提供了一系列的方法用于获取查询结果的数据,例如getString、getInt、getDate等。而ResultSetMetaData则提供了一系列的方法用于获取ResultSet的元数据,例如getColumnCount、getColumnName、getColumnType等。 通过ResultSet的封装,我们可以方便地遍历查询结果的每一行数据,并提取需要的字段值。使用ResultSetMetaData的封装,我们可以获取到结果每一列的元数据信息,例如列名、数据类型、是否可为空等。 这些封装使得我们在使用JDBC进行数据库操作时,能够更加方便地操作结果,减少了繁琐的代码编写。我们可以通过ResultSetResultSetMetaData提供的方法来获取查询结果的数据和元数据,并根据需要进行处理或展示。封装使得我们的代码更具有可读性和可维护性,并为后续的扩展和优化提供了良好的基础。 总之,JDBCResultSetResultSetMetaData的封装让我们能够更加方便地操作数据库查询结果的数据和元数据,提高了代码的效率和可读性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程火箭车

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值