1.数据库中的元数据

(1) 什么是数据元数据?
元数据(MetaData),是指定义数据结构的数据。那么数据库元数据就是指定义数据库各类对象结构的数据。 例如数据库中的数据库名,表明, 列名、用户名、版本名以及从SQL语句得到的结果中的大部分字符串是元数据
(2)数据库元数据的作用
在应用设计时能够充分地利用数据库元数据
深入理解了数据库组织结构,再去理解数据访问相关框架的实现原理会更加容易。
(3)如何获取元数据
在我们前面使用JDBC来处理数据库的接口主要有三个,即Connection,PreparedStatement和ResultSet这三个,而对于这三个接口,还可以获取不同类型的元数据,通过这些元数据类获得一些数据库的信息。下面将对这三种类型的元数据对象进行各自的介绍并通过使用MYSQL数据库进行案例说明

2 数据库元数据

2.1 概述

数据库元数据(DatabaseMetaData):是由Connection对象通过getMetaData方法获取而来,主要封装了是对数据库本身的一些整体综合信息,例如数据库的产品名称,数据库的版本号,数据库的URL,是否支持事务等等。
以下有一些关于DatabaseMetaData的常用方法:

getDatabaseProductName:获取数据库的产品名称
getDatabaseProductName:获取数据库的版本号
getUserName:获取数据库的用户名
getURL:获取数据库连接的URL
getDriverName:获取数据库的驱动名称
driverVersion:获取数据库的驱动版本号
isReadOnly:查看数据库是否只允许读操作
supportsTransactions:查看数据库是否支持事务

代码示例:
基础类:MetaDataBase

package com.shunli.autocodeutils.metadate;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

/**
 * @author shunli
 * @描述:
 * @create 2020/2/16
 * @since 1.0.0
 */
public class MetaDataBase {
    private static String userName = "root";
    private static String password = "root";
    private String tableName = "";

    //这里用的的是mysql-connector-java-8.0.19版本,所以driver和url跟老版本不同
    private static String driver = "com.mysql.cj.jdbc.Driver";
    private static String url = "jdbc:mysql://127.0.0.1:3306/[tableName]?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT";

    public MetaDataBase() {
        url = url.replace("[tableName]", tableName);
    }

    public MetaDataBase(String tableName) {
        this.tableName = tableName;
        url = url.replace("[tableName]", tableName);
    }

    /**
     * 获取连接
     * @return
     * @throws Exception
     */
    public Connection getConnection() throws Exception {
        //获取数据库的备注信息
        Properties properties = new Properties();
        //设置连接属性,使得可获取到表的REMARK(备注)
        properties.put("remarksReporting","true");
        properties.put("user",userName);
        properties.put("password",password);

        //注册驱动
        Class.forName(driver);
        return DriverManager.getConnection(url, properties);
    }

}

获取数据库元数据基本信息:

package com.shunli.autocodeutils.metadate;

import org.junit.jupiter.api.Test;

import java.sql.*;

/**
 * @author shunli
 * @描述:
 * @create 2020/2/12
 * @since 1.0.0
 */

public class DataBaseMetaDataTest {


    private MetaDataBase metaDataBase = new MetaDataBase();
    /**
     * 获取数据库元数据基本信息
     * @throws Exception
     */
    @Test
    public void getDatabaseMetaData() throws Exception {

        //获取数据库元数据
        Connection connection = metaDataBase.getConnection();
        DatabaseMetaData dbMetaData = connection.getMetaData();

        //获取数据库产品名称
        String productName = dbMetaData.getDatabaseProductName();
        System.out.println(productName);
        //获取数据库版本号
        String productVersion = dbMetaData.getDatabaseProductVersion();
        System.out.println(productVersion);
        //获取数据库用户名
        String userName = dbMetaData.getUserName();
        System.out.println(userName);
        //获取数据库连接URL
        String userUrl = dbMetaData.getURL();
        System.out.println(userUrl);
        //获取数据库驱动
        String driverName = dbMetaData.getDriverName();
        System.out.println(driverName);
        //获取数据库驱动版本号
        String driverVersion = dbMetaData.getDriverVersion();
        System.out.println(driverVersion);
        //查看数据库是否允许读操作
        boolean isReadOnly = dbMetaData.isReadOnly();
        System.out.println(isReadOnly);
        //查看数据库是否支持事务操作
        boolean supportsTransactions = dbMetaData.supportsTransactions();
        System.out.println(supportsTransactions);

        //关闭
        connection.close();
    }
}

获取数据库列表:

/**
     * 获取数据库列表
     */
    @Test
    public void getDataBaseList() throws Exception {
        //获取元数据
        Connection connection = metaDataBase.getConnection();
        DatabaseMetaData metaData = connection.getMetaData();

        //获取数据库列表
        ResultSet rs = metaData.getCatalogs();
        //遍历获取所有数据库表
        while (rs.next()) {
            //打印数据库名称
            System.out.println(rs.getString(1));
        }
        //释放资源
        rs.close();
        connection.close();
    }

获取某数据库中的所有表信息:

/**
     * 获取所有的数据库表信息
     * @throws Exception
     */
    @Test
    public void getTableInfo() throws Exception {
        //获取元数据
        Connection connection = metaDataBase.getConnection();
        DatabaseMetaData metaData = connection.getMetaData();

        /**
         * 参数说明:
         * String catalog  查询指定数据库,传空查询所有数据库的表信息
         * String schemaPattern 对于mysql来说直接传null,对于oracle:用户名(大写)
         * String tableNamePattern 查询指定表,为空时查询所有表
         * String types[] 查询数据库表类型:TABLE(表)、VIEW(视图)
         */
        //获取所有的数据库表信息
        ResultSet tablers = metaData.getTables(null, null, null, new String[]{"TABLE"});
        //拼装table
        while (tablers.next()) {
            //所属数据库
            System.out.println(tablers.getString(1));
            //所属schema
            System.out.println(tablers.getString(2));
            //表名
            System.out.println(tablers.getString(3));
            //数据库表类型
            System.out.println(tablers.getString(4));
            //数据库表备注
            System.out.println(tablers.getString(5));
        }
   }

3.参数元数据

参数元数据(ParameterMetaData):是由PreparedStatement对象通过getParameterMetaData方法获取而
来,主要是针对PreparedStatement对象和其预编译的SQL命令语句提供一些信息,ParameterMetaData能提供占位符参数的个数,获取指定位置占位符的SQL类型等等
以下有一些关于ParameterMetaData的常用方法:

getParameterCount:获取预编译SQL语句中占位符参数的个数

示例:

package com.shunli.autocodeutils.metadate;

import org.junit.Test;

import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;

/**
 * @author shunli
 * @描述:
 * @create 2020/2/16
 * @since 1.0.0
 */
public class ParameterMetaDataTest {

    private MetaDataBase metaDataBase = new MetaDataBase("o2o");
    @Test
    public void test() throws Exception {

        String sql = "select * from tb_area where area_id=?";

        Connection connection = metaDataBase.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1, "500");
        //获取ParameterMetaData对象
        ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData();
        //获取参数个数
        int paramCount = parameterMetaData.getParameterCount();
        System.out.println(paramCount);
    }
}

4.结果集元数据

结果集元数据(ResultSetMetaData):是由ResultSet对象通过getMetaData方法获取而来,主要是针对由数据库执行的SQL脚本命令获取的结果集对象ResultSet中提供的一些信息,比如结果集中的列数、指定列的名称、指定列的SQL类型等等,可以说这个是对于框架来说非常重要的一个对象。
以下有一些关于ResultSetMetaData的常用方法:

getColumnCount:获取结果集中列项目的个数
getColumnType:获取指定列的SQL类型对应于Java中Types类的字段
getColumnTypeName:获取指定列的SQL类型
getClassName:获取指定列SQL类型对应于Java中的类型(包名加类名)

示例:

package com.shunli.autocodeutils.metadate;

import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

/**
 * @author shunli
 * @描述:
 * @create 2020/2/16
 * @since 1.0.0
 */
public class ResultSetMetaDataTest {

    private MetaDataBase metaDataBase = new MetaDataBase("o2o");

    @Test
    public void test() throws Exception {
        String sql = "select * from tb_area where area_id=?";

        Connection connection = metaDataBase.getConnection();
        PreparedStatement pstmt = connection.prepareStatement(sql);
        pstmt.setString(1, "500");
        //执行sql语句
        ResultSet rs = pstmt.executeQuery();
        //获取ResultSetMetaData对象
        ResultSetMetaData metaData = rs.getMetaData();
        //获取查询字段数量
        int columnCount = metaData.getColumnCount();
        for (int i = 1; i < columnCount; i++) {
            //获取表名称
            String columnName = metaData.getColumnName(i);
            System.out.println(columnName);
            //获取java类型
            String columnClassName = metaData.getColumnClassName(i);
            System.out.println(columnClassName);
            //获取sql类型
            String columnTypeName = metaData.getColumnTypeName(i);
            System.out.println(columnTypeName);
        }
        System.out.println(columnCount);
    }

}