数据库之-元数据 DatabaseMetaData 初学(二)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 数据库之-元数据 DatabaseMetaData 初学(二)

扩展

DEMO1


在网上找了一些不错的例子demo


需要补充下contrller入口调用类、TableInfoQueyVO实体对象。这里只是写了实现方法


package cn.com.yusys.yusp.base.data.service.impl;
import cn.com.yusys.yusp.base.data.domain.vo.TableInfoQueyVO;
import cn.com.yusys.yusp.base.data.service.TableInfoQueryService;
import cn.com.yusys.yusp.commons.util.StringUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.*;
/**
 * @NAME TableInfoQueryServiceImpl
 * @VERSION 1.0.0_V
 * @DESC
 */
@Slf4j
@Service("tableInfoQueryService")
public class TableInfoQueryServiceImpl implements TableInfoQueryService {
    @Override
    public List<TableInfoQueyVO> getTableFieldInfo(String dataInfo) throws Exception {
        Map<String,String> dataSourceInfos = (Map<String, String>) JSON.parse(dataInfo);
        String dataSourceUrl = dataSourceInfos.get("dataSourceUrl");
        if (StringUtils.isBlank(dataSourceUrl)){
            throw new Exception("数据源信息为空!");
        }
        String userName = dataSourceInfos.get("userName");
        if (StringUtils.isBlank(userName)){
            throw new Exception("该用户信息为空!");
        }
        String passWord = dataSourceInfos.get("passWord");
        if (StringUtils.isBlank(passWord)){
            throw new Exception("该用户密码为空!");
        }
        String tableName = dataSourceInfos.get("tableName");
        if (StringUtils.isBlank(tableName)){
            throw new Exception("查询表名不能为空!");
        }
        Connection conn = getDataSourceConn(dataSourceUrl,userName,passWord);
        log.info("-------数据源初始化结束------");
        //获取链接元数据信息。
        DatabaseMetaData metaData = conn.getMetaData();
        List<TableInfoQueyVO> tableFields = this.getTableFields(metaData, tableName,dataSourceUrl,userName);
        return tableFields;
    }
    @Override
    public List<Map<String, String>> getTableListInfo(String dataSourceInfo) throws Exception {
        Map<String,String> dataSourceInfos = (Map<String, String>) JSON.parse(dataSourceInfo);
        String dataSourceUrl = dataSourceInfos.get("dataSourceUrl");
        if (StringUtils.isBlank(dataSourceUrl)){
            throw new Exception("数据源信息为空!");
        }
        String userName = dataSourceInfos.get("userName");
        if (StringUtils.isBlank(userName)){
            throw new Exception("该用户信息为空!");
        }
        String passWord = dataSourceInfos.get("passWord");
        if (StringUtils.isBlank(passWord)){
            throw new Exception("该用户密码为空!");
        }
        log.info("开始查询数据源{}-{}-{},信息",dataSourceUrl,userName,passWord);
        Connection conn = getDataSourceConn(dataSourceUrl,userName,passWord);
        log.info("-------数据源初始化结束------");
        //获取链接元数据信息。
        DatabaseMetaData metaData = conn.getMetaData();
        List<Map<String, String>> tableList = this.getTableInfoList(metaData,dataSourceUrl,userName);
        closeConnection(conn);
        return tableList;
    }
    /**
     * 根据数据源 获取改数据源下说有的表结构信息。
     *
     * @param dataSourceInfo
     * @return
     */
    @Override
    public List<Map<String, Object>> getTableInfos(String dataSourceInfo) throws Exception{
        Map<String,String> dataSourceInfos = (Map<String, String>) JSON.parse(dataSourceInfo);
        String dataSourceUrl = dataSourceInfos.get("dataSourceUrl");
        if (StringUtils.isBlank(dataSourceUrl)){
            throw new Exception("数据源信息为空!");
        }
        String userName = dataSourceInfos.get("userName");
        if (StringUtils.isBlank(userName)){
            throw new Exception("该用户信息为空!");
        }
        String passWord = dataSourceInfos.get("passWord");
        if (StringUtils.isBlank(passWord)){
            throw new Exception("该用户密码为空!");
        }
        log.info("开始查询数据源{},信息",dataSourceUrl,userName,passWord);
        List<Map<String,Object>> listInfos = new ArrayList<>();
        Connection conn = getDataSourceConn(dataSourceUrl,userName,passWord);
        log.info("-------数据源初始化结束------");
        //获取链接元数据信息。
        DatabaseMetaData metaData = conn.getMetaData();
        List<Map<String, String>> tableList = this.getTableList(metaData,dataSourceUrl,userName);
        for (Map<String, String> stringMap : tableList) {
            Map<String,Object> tableInfoMap = new HashMap<>();
            for (String ss : stringMap.keySet()) {
                tableInfoMap.put("tableName",ss);
                List<TableInfoQueyVO> tableFields = this.getTableFields(metaData, ss,dataSourceUrl,userName);
                tableInfoMap.put("tableFields",tableFields);
            }
            listInfos.add(tableInfoMap);
        }
        //关闭链接
        closeConnection(conn);
        log.info("查询数据源信息处理结束!");
        return listInfos;
    }
    /**
     * 获取数据库 链接
     * @param dataSourceUrl
     * @param userName
     * @param passWord
     * @return
     * @throws Exception
     */
    public Connection getDataSourceConn(String dataSourceUrl,String userName,String passWord) throws Exception{
        log.info("-------数据源初始化开始------");
        Properties pros = new Properties();
        pros.setProperty("user",userName);
        pros.setProperty("password",passWord);
        pros.setProperty("remarks","true");
        if (dataSourceUrl.contains("mysql")){
          //需要加入个可以获取 REMARKS 的信息,不然获取到的为空
            pros.setProperty("useInformationSchema","true");
            Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
        }else if (dataSourceUrl.contains("oracle")){
            Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
        }else {
            throw new Exception("不支持的数据类型");
        }
//        DriverManager.getConnection(dataSourceUrl,userName,passWord);
        return DriverManager.getConnection(dataSourceUrl,pros);
    }
    /**
     * 获取该数据源下 所有的列表
     * @param metaData
     * @param dataSourceUrl
     * @return
     * @throws Exception
     */
    public List<Map<String,String>> getTableList(DatabaseMetaData metaData,String dataSourceUrl,String userName) throws Exception{
        log.info("-------获取数据库表 列表开始---------");
        List<Map<String,String>> tableInfoList = new ArrayList<>();
        String dataBaseName = null;
        if (dataSourceUrl.contains("mysql")){
            dataBaseName =dataSourceUrl.substring(dataSourceUrl.lastIndexOf("/")+1,dataSourceUrl.indexOf("?"));
            userName = null;
        }
        ResultSet tables = metaData.getTables(dataBaseName, userName, "%", new String[]{"TABLE"});
        while (tables.next()){
            Map<String,String> tableInfoMap = new HashMap<>();
            tableInfoMap.put(tables.getString("TABLE_NAME"),tables.getString("REMARKS"));
            tableInfoList.add(tableInfoMap);
        }
        //打印测试表
        log.info("-------获取数据库表 列表结束---------");
        return tableInfoList;
    }
    /**
     * 获取表中,所有的表的字段
     * @param metaData
     * @param tableName
     * @param dataSourceUrl
     * @return
     * @throws Exception
     */
    public List<TableInfoQueyVO> getTableFields(DatabaseMetaData metaData,String tableName,String dataSourceUrl,String userName) throws Exception{
        List<TableInfoQueyVO> tableFieldList = new ArrayList<>();
    //兼容oracle和mysql
        String dataBaseName = null;
        if (dataSourceUrl.contains("mysql")){
            dataBaseName =dataSourceUrl.substring(dataSourceUrl.lastIndexOf("/")+1,dataSourceUrl.indexOf("?"));
            userName = null;
        }
        //mysql 使用dataBaseName ,oracle 使用 userName
        ResultSet dataColumns = metaData.getColumns(dataBaseName, userName, tableName, "%");
        ResultSet keys = metaData.getPrimaryKeys(dataBaseName, null, tableName);
        Object entityInstance = this.getEntityInstance(getClassNameList(tableName));
        Map<String,String> breakMap = new HashMap<>();
         while(null!=dataColumns&&dataColumns.next()){
            TableInfoQueyVO tiqv = new TableInfoQueyVO();
            if (!StringUtils.isEmpty(breakMap.get(dataColumns.getString("COLUMN_NAME")))){
                break;
            }
            breakMap.put(dataColumns.getString("COLUMN_NAME"),dataColumns.getString("TYPE_NAME"));
             //比较字段值
            if (this.compareFieldType(dataColumns.getString("COLUMN_NAME"),
                     dataColumns.getString("TYPE_NAME"),entityInstance)){
                 tiqv.setFieldType(dataColumns.getString("TYPE_NAME"));
            }
            tiqv.setFieldCode(dataColumns.getString("COLUMN_NAME"));
            tiqv.setFieldName(dataColumns.getString("REMARKS"));
//            tiqv.setFieldType(dataColumns.getString("TYPE_NAME"));
            String primaryKey = null;
            if (null!=keys&&keys.next()){
                primaryKey = keys.getString("COLUMN_NAME");
                String primaryKeyType = keys.getString("PK_NAME");
                if ("PRIMARY".equals(primaryKeyType)&&primaryKey.equals(tiqv.getFieldCode())){
                    tiqv.setIsKey(primaryKey);
                }
            }
            tableFieldList.add(tiqv);
        }
        breakMap.clear();
        return tableFieldList;
    }
    /**
     * 关闭链接
     * @param conn
     * @throws Exception
     */
    public void closeConnection(Connection conn) throws Exception{
        if (conn.isClosed()){
            log.info("数据源链接已关闭!");
            return;
        }else {
            conn.close();
            log.info("数据源链接关闭结束");
        }
    }
    /**
     * 获取实体对象实例
     * @param className
     * @return
     * @throws Exception
     */
    public Object getEntityInstance(List<String> className) throws Exception{
        Class<?> aClass;
        for (String s : className) {
            try {
                aClass = Class.forName(s);
            } catch (ClassNotFoundException e) { //如果是不存在的地址,继续
                continue;
            }
            if (null != aClass){
                return aClass.newInstance();
            }
        }
        return null;
    }
    /**
     * 获取 实例所在的地址
     * @param tableName
     * @return
     */
    public List<String> getClassNameList(String tableName){
        //新增工程目录需要在这里新增 entity 路径
        List<String> classPathList = new ArrayList<>();
        classPathList.add("cn.com.yusys.yusp.base.data.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.base.engine.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.data.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.message.entity.");
        classPathList.add("cn.com.yusys.yusp.notice.entity.");
        classPathList.add("cn.com.yusys.yusp.oca.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.strategy.data.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.strategy.engine.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.strategy.manager.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.stream.engine.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.stream.manager.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.untiy.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.warning.data.domain.entity.");
        classPathList.add("cn.com.yusys.yusp.warning.engine.domain.entity.");
        List<String> classPathContent = new ArrayList<>();
        String[] split = tableName.split("_");
        String tableNameTmpA = "";
        //实体类类型拼接
        for (String s : split) {
            tableNameTmpA = tableNameTmpA+org.apache.commons.lang.StringUtils.capitalize(s);
        }
        String tableNameTmpB = "";
        for (int i = 1; i < split.length; i++) {
            tableNameTmpB = tableNameTmpB+org.apache.commons.lang.StringUtils.capitalize(split[i]);
        }
        //组装成全路径,并保存,因为不确定 entity 到底是那种,所有两种都组装
        for (String s : classPathList) {
            classPathContent.add(s+tableNameTmpA+"Entity");
            classPathContent.add(s+tableNameTmpA+"Entity");
        }
        return classPathContent;
    }
    /**
     * 比较数据库中字段类型和实体类中的类型是否一致
     * @param fieldName
     * @param fieldType
     * @param entityInstance
     * @return
     */
    public boolean compareFieldType(String fieldName,String fieldType,Object entityInstance){
        if (org.springframework.util.StringUtils.isEmpty(entityInstance)){
            return true;
        }
        Field[] declaredFields = entityInstance.getClass().getDeclaredFields();
        if (org.springframework.util.StringUtils.isEmpty(declaredFields)){
            return false;
        }
        String[] split = fieldName.split("_");
        String fieldNameTmp = split[0].toLowerCase();
        for (int i = 1; i < split.length; i++) {
            fieldNameTmp = fieldNameTmp+org.apache.commons.lang.StringUtils.capitalize(split[i].toLowerCase());
        }
        for (Field declaredField : declaredFields) {
            //字段为空 继续下次循环
            if (org.springframework.util.StringUtils.isEmpty(declaredField)){
                continue;
            }
            //未知数据类型
            if (StringUtils.isBlank(FieldTypeRef.getRefTypeCode(fieldType))){
                return false;
            }
            //如果字段名一致,且字段在映射项中
            if (fieldNameTmp.equals(declaredField.getName())
                    &&declaredField.getType().getName().contains(FieldTypeRef.getRefTypeCode(fieldType))){
                return true;
            }
        }
        return false;
    }
    public List<Map<String,String>> getTableInfoList(DatabaseMetaData metaData,String dataSourceUrl,String userName) throws Exception{
        log.info("-------获取数据库表 列表开始---------");
        List<Map<String,String>> tableInfoList = new ArrayList<>();
        String dataBaseName = null;
        if (dataSourceUrl.contains("mysql")){
            dataBaseName =dataSourceUrl.substring(dataSourceUrl.lastIndexOf("/")+1,dataSourceUrl.indexOf("?"));
            userName = null;
        }
        ResultSet tables = metaData.getTables(dataBaseName, userName, "%", new String[]{"TABLE"});
        while (tables.next()){
            Map<String,String> tableInfoMap = new HashMap<>();
            tableInfoMap.put("tableCode",tables.getString("TABLE_NAME"));
            tableInfoMap.put("tableName",tables.getString("REMARKS"));
            tableInfoList.add(tableInfoMap);
        }
        //打印测试表
        log.info("-------获取数据库表 列表结束---------");
        return tableInfoList;
    }
}
/**
 * 字段类型枚举类
 */
enum FieldTypeRef{
    VAR("VARCHAR","String"),
    TEXT("TEXT","String"),
    INT("INT","Integer"),
    DATETIME("DATETIME","Date"),
    CHAR("CHAR","String"),
    DECIMAL("DECIMAL","BigDecimal"),
    FLOAT("FLOAT","float")
    ;
    private String typeCode;
    private String refTypeCoe;
    public String getTypeCode() {
        return typeCode;
    }
    public void setTypeCode(String typeCode) {
        this.typeCode = typeCode;
    }
    public String getRefTypeCoe() {
        return refTypeCoe;
    }
    public void setRefTypeCoe(String refTypeCoe) {
        this.refTypeCoe = refTypeCoe;
    }
    FieldTypeRef(String typeCode, String refTypeCoe) {
        this.typeCode = typeCode;
        this.refTypeCoe = refTypeCoe;
    }
    public static String getRefTypeCode(String key){
        for (FieldTypeRef value : FieldTypeRef.values()) {
            if (key.equals(value.typeCode)){
                return value.getRefTypeCoe();
            }
        }
        return null;
    }
}


getTables

检索给定目录中可用表的描述。仅返回与目录、模式、表名称和类型条件匹配的表描述。它们按 TABLE_TYPE、TABLE_CAT、TABLE_SCHEM 和 TABLE_NAME 排序。


/**
     * 检索给定目录中可用表的描述。
     * 只有与目录、模式、表匹配的表描述
     * 返回名称和类型标准。他们被订购
     * <code>TABLE_TYPE</code>, <code>TABLE_CAT</code>,
     * <code>TABLE_SCHEM</code> 和 <code>TABLE_NAME</code>。
     * <P>
     * 每个表描述都有以下列:
     * <OL>
     * <LI><B>TABLE_CAT</B> String {@code =>} 表目录(可能是<code>null</code>)
     * <LI><B>TABLE_SCHEM</B> 字符串 {@code =>} 表模式(可能是 <code>null</code>)
     * <LI><B>TABLE_NAME</B> 字符串 {@code =>} 表名
     * <LI><B>TABLE_TYPE</B> 字符串 {@code =>} 表类型。典型的类型是“TABLE”,
     *“视图”、“系统表”、“全局临时”、
     *“本地临时”、“别名”、“同义词”。
     * <LI><B>REMARKS</B> String {@code =>} 对表格的解释性注释
     * <LI><B>TYPE_CAT</B> String {@code =>} 类型目录(可能是<code>null</code>)
     * <LI><B>TYPE_SCHEM</B> String {@code =>} 类型模式(可能是 <code>null</code>)
     * <LI><B>TYPE_NAME</B> String {@code =>} 类型名称(可能是<code>null</code>)
     * <LI><B>SELF_REFERENCING_COL_NAME</B> String {@code =>} 指定名称
     * 类型表的“标识符”列(可能是 <code>null</code>)
     * <LI><B>REF_GENERATION</B> String {@code =>} 指定值如何在
     * 创建 SELF_REFERENCING_COL_NAME。值为
     *“系统”、“用户”、“派生”。 (可能是 <code>null</code>)
     * </OL>
     *
     * <P><B>注意:</B>有些数据库可能不会返回信息
     * 所有表格。
     *
     * @param catalog 一个目录名;必须与目录名称匹配
     * 存储在数据库中; "" 检索那些没有目录的;
     * <code>null</code> 表示不应该使用目录名称来缩小搜索
     * @param schemaPattern 模式名称模式;必须与架构名称匹配
     * 因为它存储在数据库中; "" 检索那些没有模式的;
     * <code>null</code> 表示不应该使用模式名称来缩小范围搜索
     * @param tableNamePattern 一个表名模式;必须匹配存储在数据库中的表名
     * @param types 表类型列表,必须来自表类型列表
     * 从 {@link #getTableTypes} 返回,包括; <code>null</code> 返回所有类型
     * @return <code>ResultSet</code> - 每行是一个表描述
     * @exception SQLException 如果发生数据库访问错误
     * @see #getSearchStringEscape
     */


参数:


String catalog: mysql下就是数据库名称,oracle下就是instance名;可以为null,可以为“”。解释参见@param catalog


String schemaPattern:mysql下就是数据库名称,oracle中就是用户名.解释参见@param schemaPattern


String tableNamePattern: 数据表名称


String[] types: 查询的表类型,参考注解中的解释


getColumns


/**
     * 检索可用的表列的描述
     * 指定目录。
     *
     * <P>只有与目录、模式、表匹配的列描述
     * 和列名条件被返回。他们被订购
     * <code>TABLE_CAT</code>,<code>TABLE_SCHEM</code>,
     * <code>TABLE_NAME</code> 和 <code>ORDINAL_POSITION</code>。
     *
     * <P>每列描述都有以下列:
     * <OL>
     * <LI><B>TABLE_CAT</B> String {@code =>} 表目录(可能是<code>null</code>)
     * <LI><B>TABLE_SCHEM</B> 字符串 {@code =>} 表模式(可能是 <code>null</code>)
     * <LI><B>TABLE_NAME</B> 字符串 {@code =>} 表名
     * <LI><B>COLUMN_NAME</B> 字符串 {@code =>} 列名
     * <LI><B>DATA_TYPE</B> int {@code =>} 来自 java.sql.Types 的 SQL 类型
     * <LI><B>TYPE_NAME</B> String {@code =>} 数据源依赖类型名称,
     * 对于 UDT,类型名称是完全限定的
     * <LI><B>COLUMN_SIZE</B> int {@code =>} 列大小。
     * <LI><B>BUFFER_LENGTH</B> 未使用。
     * <LI><B>DECIMAL_DIGITS</B> int {@code =>} 小数位数。对于其中的数据类型返回 Null
     * DECIMAL_DIGITS 不适用。
     * <LI><B>NUM_PREC_RADIX</B> int {@code =>} 基数(通常为 10 或 2)
     * <LI><B>NULLABLE</B> int {@code =>} 允许为 NULL。
     * <UL>
     * <LI> columnNoNulls - 可能不允许 <code>NULL</code> 值
     * <LI> columnNullable - 绝对允许 <code>NULL</code> 值
     * <LI> columnNullableUnknown - 可空性未知
     * </UL>
     * <LI><B>REMARKS</B> String {@code =>} 注释描述列(可能是<code>null</code>)
     * <LI><B>COLUMN_DEF</B> String {@code =>} 列的默认值,当值用单引号括起来时应解释为字符串(可能为<code>null</code >)
     * <LI><B>SQL_DATA_TYPE</B> int {@code =>} 未使用
     * <LI><B>SQL_DATETIME_SUB</B> int {@code =>} 未使用
     * <LI><B>CHAR_OCTET_LENGTH</B> int {@code =>} 用于 char 类型
     * 列中的最大字节数
     * <LI><B>ORDINAL_POSITION</B> int {@code =>} 表中列的索引
     *(从 1 开始)
     * <LI><B>IS_NULLABLE</B> String {@code =>} ISO 规则用于确定列的可空性。
     * <UL>
     * <LI> YES --- 如果列可以包含 NULL
     * <LI> NO --- 如果列不能包含 NULL
     * <LI> 空字符串 --- 如果
     * 列未知
     * </UL>
     * <LI><B>SCOPE_CATALOG</B> String {@code =>} 范围表的目录
     * 引用属性(如果 DATA_TYPE 不是 REF,则为 <code>null</code>)
     * <LI><B>SCOPE_SCHEMA</B> String {@code =>} 范围表的模式
     * 引用属性(如果 DATA_TYPE 不是 REF,则为 <code>null</code>)
     * <LI><B>SCOPE_TABLE</B> String {@code =>} 这个范围的表名
     * 引用属性(如果 DATA_TYPE 不是 REF,则为 <code>null</code>)
     * <LI><B>SOURCE_DATA_TYPE</B> 短 {@code =>} 不同类型或用户生成的源类型
     * Ref 类型,来自 java.sql.Types 的 SQL 类型(<code>null</code> if DATA_TYPE
     * 不是 DISTINCT 或用户生成的 REF)
     * <LI><B>IS_AUTOINCREMENT</B> String {@code =>} 表示该列是否自动递增
     * <UL>
     * <LI> YES --- 如果列是自动递增的
     * <LI> NO --- 如果列不是自动递增的
     * <LI> 空字符串 --- 如果无法确定列是否自动递增
     * </UL>
     * <LI><B>IS_GENERATEDCOLUMN</B> String {@code =>} 表示这是否是生成列
     * <UL>
     * <LI> YES --- 如果这是一个生成的列
     * <LI> NO --- 如果这不是生成的列
     * <LI> 空字符串 --- 如果无法确定这是否是生成的列
     * </UL>
     * </OL>
     *
     * <p>COLUMN_SIZE 列指定给定列的列大小。
     * 对于数值数据,这是最大精度。对于字符数据,这是字符长度。
     * 对于日期时间数据类型,这是字符串表示的字符长度(假设
     * 小数秒组件的最大允许精度)。对于二进制数据,这是以字节为单位的长度。对于 ROWID 数据类型,
     * 这是以字节为单位的长度。对于其中的数据类型返回 Null
     * 列大小不适用。
     * @param catalog 一个目录名; 必须与目录名称匹配
      * 存储在数据库中; "" 检索那些没有目录的;
      * <code>null</code> 表示不应该使用目录名称来缩小搜索
      * @param schemaPattern 模式名称模式; 
      * 必须与架构名称匹配因为它存储在数据库中; 
      * "" 检索那些没有模式的;
      * <code>null</code> 表示不应该使用模式名称来缩小范围搜索
      * @param tableNamePattern 一个表名模式; 必须匹配
      * 存储在数据库中的表名
      * @param columnNamePattern 列名模式; 必须与列匹配
      * 名称,因为它存储在数据库中
      * @return <code>ResultSet</code> - 每行是一个列描述
      * @exception SQLException 如果发生数据库访问错误
      * @see #getSearchStringEscape
      */


DEMO2


package com.example.democrud.democurd.controller;
import oracle.jdbc.driver.OracleConnection;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * @Description: JDBC操作元数据示例-- DatabaseMetaData接口
 * @version V1.0
 */
public class JdbcUtil {
    //5.7 版本 左右的用这个
    //   private static String DRIVER="com.mysql.jdbc.Driver";  ip,端口号/库名
    // private static String URL="jdbc:mysql://127.0.0.1:3306/atguigudb;
    //8.0的版本  获得驱动  获得url
    private static String DRIVER="com.mysql.cj.jdbc.Driver";
    private static String URL="jdbc:mysql://127.0.0.1:3306/atguigudb?serverTimezone=UTC&nullCatalogMeansCurrent=true&RemarksReporting=true";
   // private static String URL = "jdbc:oracle:thin:@localhost:test";
    //获得连接数据库的用户名
    private static String USER = "root";
    //获得连接数据库的密码
    private static String PASS = "root";
    static {
        try {
            //初始化JDBC驱动并让驱动加载到jvm中
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection(){
        Connection conn = null;
        try {
            //连接数据库
        /*
         * 设置可获取REMARK备注信息
        Properties props =new Properties();
        props.put("remarksReporting","true");
        props.put("user", USER);
        props.put("password", PASS);
        conn =DriverManager.getConnection(URL,props);*/
            conn = DriverManager.getConnection(URL,USER,PASS);
            conn.setAutoCommit(true);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
    //关闭连接
    public static void close(Object o){
        if (o == null){
            return;
        }
        if (o instanceof ResultSet){
            try {
                ((ResultSet)o).close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } else if(o instanceof Statement){
            try {
                ((Statement)o).close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } else if (o instanceof Connection){
            Connection c = (Connection)o;
            try {
                if (!c.isClosed()){
                    c.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(ResultSet rs, Statement stmt,
                             Connection conn){
        close(rs);
        close(stmt);
        close(conn);
    }
    public static void close(ResultSet rs,
                             Connection conn){
        close(rs);
        close(conn);
    }
    /**
     * @Description: 获取数据库相关信息
     * @author: chenzw
     * @CreateTime: 2014-1-27 下午5:09:12
     * @throws
     */
    public static void getDataBaseInfo() {
        Connection conn =  getConnection();
        ResultSet rs = null;
        try{
            DatabaseMetaData dbmd = conn.getMetaData();
            System.out.println("数据库已知的用户: "+ dbmd.getUserName());
            System.out.println("数据库的系统函数的逗号分隔列表: "+ dbmd.getSystemFunctions());
            System.out.println("数据库的时间和日期函数的逗号分隔列表: "+ dbmd.getTimeDateFunctions());
            System.out.println("数据库的字符串函数的逗号分隔列表: "+ dbmd.getStringFunctions());
            System.out.println("数据库供应商用于 'schema' 的首选术语: "+ dbmd.getSchemaTerm());
            System.out.println("数据库URL: " + dbmd.getURL());
            System.out.println("是否允许只读:" + dbmd.isReadOnly());
            System.out.println("数据库的产品名称:" + dbmd.getDatabaseProductName());
            System.out.println("数据库的版本:" + dbmd.getDatabaseProductVersion());
            System.out.println("驱动程序的名称:" + dbmd.getDriverName());
            System.out.println("驱动程序的版本:" + dbmd.getDriverVersion());
            System.out.println("数据库中使用的表类型");
            rs = dbmd.getTableTypes();
            while (rs.next()) {
                System.out.println(rs.getString("TABLE_TYPE"));
            }
        }catch (SQLException e){
            e.printStackTrace();
        } finally{
            JdbcUtil.close(rs,conn);
        }
    }
    /**
     * @Description:获得数据库中所有Schemas(对应于oracle中的Tablespace)
     */
    public static void getSchemasInfo(){
        Connection conn =  getConnection();
        ResultSet rs = null;
        try{
            DatabaseMetaData dbmd = conn.getMetaData();
            rs = dbmd.getSchemas();
            while (rs.next()){
                String tableSchem = rs.getString("TABLE_SCHEM");
                System.out.println(tableSchem);
            }
        } catch (SQLException e){
            e.printStackTrace();
        } finally{
            JdbcUtil.close(rs,conn);
        }
    }
    /**
     * @Description: 获取数据库中所有的表信息
     */
    public static void getTablesList() {
        Connection conn =  getConnection();
        ResultSet rs = null;
        try {
            /**
             * 设置连接属性,使得可获取到表的REMARK(备注)
             */
           // ((OracleConnection)conn).setRemarksReporting(true);
            DatabaseMetaData dbmd = conn.getMetaData();
            String[] types = { "TABLE" };
            rs = dbmd.getTables(null, null, "%", types);
            while (rs.next()) {
                String tableName = rs.getString("TABLE_NAME");  //表名
                String tableType = rs.getString("TABLE_TYPE");  //表类型
                String remarks = rs.getString("REMARKS");       //表备注
                System.out.println(tableName + " - " + tableType + " - " + remarks);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally{
            JdbcUtil.close(rs,conn);
        }
    }
    /**
     * @Description: 获取某表信息
     * @throws
     */
    public static void getTablesInfo(){
        Connection conn =  getConnection();
        ResultSet rs = null;
        try {
            /**
             * 设置连接属性,使得可获取到表的REMARK(备注)
             */
         //   ((OracleConnection)conn).setRemarksReporting(true);
            DatabaseMetaData dbmd = conn.getMetaData();
            /**
             * 获取给定类别中使用的表的描述。
             * 方法原型:ResultSet getTables(String catalog,String schemaPattern,String tableNamePattern,String[] types);
             * catalog - 表所在的类别名称;""表示获取没有类别的列,null表示获取所有类别的列。
             * schema - 表所在的模式名称(oracle中对应于Tablespace);""表示获取没有模式的列,null标识获取所有模式的列; 可包含单字符通配符("_"),或多字符通配符("%");
             * tableNamePattern - 表名称;可包含单字符通配符("_"),或多字符通配符("%");
             * types - 表类型数组; "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM";null表示包含所有的表类型;可包含单字符通配符("_"),或多字符通配符("%");
             */
              //countries 换成自己需要查询的表名
            rs = dbmd.getTables(null, null, "countries", new String[]{"TABLE","VIEW"});
            while(rs.next()){
                String tableCat = rs.getString("TABLE_CAT");  //表类别(可为null)
                String tableSchemaName = rs.getString("TABLE_SCHEM");//表模式(可能为空),在oracle中获取的是命名空间,其它数据库未知
                String tableName = rs.getString("TABLE_NAME");  //表名
                String tableType = rs.getString("TABLE_TYPE");  //表类型,典型的类型是 "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。
                String remarks = rs.getString("REMARKS");       //表备注
                System.out.println(tableCat + " - " + tableSchemaName + " - " +tableName + " - " + tableType + " - "
                        + remarks);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }finally{
            JdbcUtil.close(rs,conn);
        }
    }
    /**
     * @Description: 获取表主键信息
     * @throws
     */
    public static void getPrimaryKeysInfo() {
        Connection conn =  getConnection();
        ResultSet rs = null;
        try{
            DatabaseMetaData dbmd = conn.getMetaData();
            /**
             * 获取对给定表的主键列的描述
             * 方法原型:ResultSet getPrimaryKeys(String catalog,String schema,String table);
             * catalog - 表所在的类别名称;""表示获取没有类别的列,null表示获取所有类别的列。
             * schema - 表所在的模式名称(oracle中对应于Tablespace);""表示获取没有模式的列,null标识获取所有模式的列; 可包含单字符通配符("_"),或多字符通配符("%");
             * table - 表名称;可包含单字符通配符("_"),或多字符通配符("%");
             */
            rs = dbmd.getPrimaryKeys(null, null, "CUST_INTER_TF_SERVICE_REQ");
            while (rs.next()){
                String tableCat = rs.getString("TABLE_CAT");  //表类别(可为null)
                String tableSchemaName = rs.getString("TABLE_SCHEM");//表模式(可能为空),在oracle中获取的是命名空间,其它数据库未知
                String tableName = rs.getString("TABLE_NAME");  //表名
                String columnName = rs.getString("COLUMN_NAME");//列名
                short keySeq = rs.getShort("KEY_SEQ");//序列号(主键内值1表示第一列的主键,值2代表主键内的第二列)
                String pkName = rs.getString("PK_NAME"); //主键名称
                System.out.println(tableCat + " - " + tableSchemaName + " - " + tableName + " - " + columnName + " - "
                        + keySeq + " - " + pkName);
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally{
            JdbcUtil.close(rs,conn);
        }
    }
    /**
     * @Description: 获取表索引信息
     * @throws
     */
    public static void getIndexInfo() {
        Connection conn =  getConnection();
        ResultSet rs = null;
        try{
            DatabaseMetaData dbmd = conn.getMetaData();
            /**
             * 获取给定表的索引和统计信息的描述
             * 方法原型:ResultSet getIndexInfo(String catalog,String schema,String table,boolean unique,boolean approximate)
             * catalog - 表所在的类别名称;""表示获取没有类别的列,null表示获取所有类别的列。
             * schema - 表所在的模式名称(oracle中对应于Tablespace);""表示获取没有模式的列,null标识获取所有模式的列; 可包含单字符通配符("_"),或多字符通配符("%");
             * table - 表名称;可包含单字符通配符("_"),或多字符通配符("%");
             * unique - 该参数为 true时,仅返回唯一值的索引; 该参数为 false时,返回所有索引;
             * approximate - 该参数为true时,允许结果是接近的数据值或这些数据值以外的值;该参数为 false时,要求结果是精确结果;
             */
            rs = dbmd.getIndexInfo(null, null, "CUST_INTER_TF_SERVICE_REQ", false, true);
            while (rs.next()){
                String tableCat = rs.getString("TABLE_CAT");  //表类别(可为null)
                String tableSchemaName = rs.getString("TABLE_SCHEM");//表模式(可能为空),在oracle中获取的是命名空间,其它数据库未知
                String tableName = rs.getString("TABLE_NAME");  //表名
                boolean nonUnique = rs.getBoolean("NON_UNIQUE");// 索引值是否可以不唯一,TYPE为 tableIndexStatistic时索引值为 false;
                String indexQualifier = rs.getString("INDEX_QUALIFIER");//索引类别(可能为空),TYPE为 tableIndexStatistic 时索引类别为 null;
                String indexName = rs.getString("INDEX_NAME");//索引的名称 ;TYPE为 tableIndexStatistic 时索引名称为 null;
                /**
                 * 索引类型:
                 *  tableIndexStatistic - 此标识与表的索引描述一起返回的表统计信息
                 *  tableIndexClustered - 此为集群索引
                 *  tableIndexHashed - 此为散列索引
                 *  tableIndexOther - 此为某种其他样式的索引
                 */
                short type = rs.getShort("TYPE");//索引类型;
                short ordinalPosition = rs.getShort("ORDINAL_POSITION");//在索引列顺序号;TYPE为 tableIndexStatistic 时该序列号为零;
                String columnName = rs.getString("COLUMN_NAME");//列名;TYPE为 tableIndexStatistic时列名称为 null;
                String ascOrDesc = rs.getString("ASC_OR_DESC");//列排序顺序:升序还是降序[A:升序; B:降序];如果排序序列不受支持,可能为 null;TYPE为 tableIndexStatistic时排序序列为 null;
                int cardinality = rs.getInt("CARDINALITY");   //基数;TYPE为 tableIndexStatistic 时,它是表中的行数;否则,它是索引中唯一值的数量。
                int pages = rs.getInt("PAGES"); //TYPE为 tableIndexStatisic时,它是用于表的页数,否则它是用于当前索引的页数。
                String filterCondition = rs.getString("FILTER_CONDITION"); //过滤器条件,如果有的话(可能为 null)。
                System.out.println(tableCat + " - " + tableSchemaName + " - " + tableName + " - " + nonUnique + " - "
                        + indexQualifier + " - " + indexName + " - " + type + " - " + ordinalPosition + " - " + columnName
                        + " - " + ascOrDesc + " - " + cardinality + " - " + pages + " - " + filterCondition);
            }
        } catch (SQLException e){
            e.printStackTrace();
        } finally{
            JdbcUtil.close(rs,conn);
        }
    }
    /**
     * @Description: 获取表中列值信息
     * @throws
     */
    public static void getColumnsInfo(){
        Connection conn =  getConnection();
        ResultSet rs = null;
        try{
            /**
             * 设置连接属性,使得可获取到列的REMARK(备注)
             */
           // ((OracleConnection)conn).setRemarksReporting(true);
            DatabaseMetaData dbmd = conn.getMetaData();
            /**
             * 获取可在指定类别中使用的表列的描述。
             * 方法原型:ResultSet getColumns(String catalog,String schemaPattern,String tableNamePattern,String columnNamePattern)
             * catalog - 表所在的类别名称;""表示获取没有类别的列,null表示获取所有类别的列。
             * schema - 表所在的模式名称(oracle中对应于Tablespace);""表示获取没有模式的列,null标识获取所有模式的列; 可包含单字符通配符("_"),或多字符通配符("%");
             * tableNamePattern - 表名称;可包含单字符通配符("_"),或多字符通配符("%");
             * columnNamePattern - 列名称; ""表示获取列名为""的列(当然获取不到);null表示获取所有的列;可包含单字符通配符("_"),或多字符通配符("%");
             */
             //countries 换成自己需要查询的表名
            rs =dbmd.getColumns(null, null, "countries", null);
            while(rs.next()){
                String tableCat = rs.getString("TABLE_CAT");  //表类别(可能为空)
                String tableSchemaName = rs.getString("TABLE_SCHEM");  //表模式(可能为空),在oracle中获取的是命名空间,其它数据库未知
                String tableName_ = rs.getString("TABLE_NAME");  //表名
                String columnName = rs.getString("COLUMN_NAME");  //列名
                int dataType = rs.getInt("DATA_TYPE");     //对应的java.sql.Types的SQL类型(列类型ID)
                String dataTypeName = rs.getString("TYPE_NAME");  //java.sql.Types类型名称(列类型名称)
                int columnSize = rs.getInt("COLUMN_SIZE");  //列大小
                int decimalDigits = rs.getInt("DECIMAL_DIGITS");  //小数位数
                int numPrecRadix = rs.getInt("NUM_PREC_RADIX");  //基数(通常是10或2) --未知
                /**
                 *  0 (columnNoNulls) - 该列不允许为空
                 *  1 (columnNullable) - 该列允许为空
                 *  2 (columnNullableUnknown) - 不确定该列是否为空
                 */
                int nullAble = rs.getInt("NULLABLE");  //是否允许为null
                String remarks = rs.getString("REMARKS");  //列描述
                String columnDef = rs.getString("COLUMN_DEF");  //默认值
                int charOctetLength = rs.getInt("CHAR_OCTET_LENGTH");    // 对于 char 类型,该长度是列中的最大字节数
                int ordinalPosition = rs.getInt("ORDINAL_POSITION");   //表中列的索引(从1开始)
                /**
                 * ISO规则用来确定某一列的是否可为空(等同于NULLABLE的值:[ 0:'YES'; 1:'NO'; 2:''; ])
                 * YES -- 该列可以有空值;
                 * NO -- 该列不能为空;
                 * 空字符串--- 不知道该列是否可为空
                 */
                String isNullAble = rs.getString("IS_NULLABLE");
                /**
                 * 指示此列是否是自动递增
                 * YES -- 该列是自动递增的
                 * NO -- 该列不是自动递增
                 * 空字串--- 不能确定该列是否自动递增
                 */
                //String isAutoincrement = rs.getString("IS_AUTOINCREMENT");   //该参数测试报错
                System.out.println(tableCat + " - " + tableSchemaName + " - " + tableName_ + " - " + columnName +
                        " - " + dataType + " - " + dataTypeName + " - " + columnSize + " - " + decimalDigits + " - "
                        + numPrecRadix + " - " + nullAble + " - " + remarks + " - " + columnDef + " - " + charOctetLength
                        + " - " + ordinalPosition + " - " + isNullAble );
            }
        }catch(SQLException ex){
            ex.printStackTrace();
        }finally{
            JdbcUtil.close(rs,conn);
        }
    }
    /**
     * @Description: TODO
     * @param args
     * @throws
     */
    public static void main(String[] args) {
        getDataBaseInfo();  //获取数据库信息
        getSchemasInfo(); //获取数据库所有Schema
        System.out.println("--------");
        getTablesList();  //获取某用户下所有的表
        System.out.println("--------");
        getTablesInfo();  //获取表信息
        getPrimaryKeysInfo(); //获取表主键信息
        getIndexInfo();  //获取表索引信息
        System.out.println("--------");
        getColumnsInfo(); //获取表中列值信息 需要指定自己的表等参数
    }
}


执行结果为

D:\工作磁盘\java环境\jdk1.8.0_181\bin\java.exe "-javaagent:D:\工作磁盘\java环境\idea\IntelliJ IDEA 2021.3.1\lib\idea_rt.jar=64076:D:\工作磁盘\java环境\idea\IntelliJ IDEA 2021.3.1\bin" -Dfile.encoding=UTF-8 -classpath D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\charsets.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\deploy.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\access-bridge-32.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\dnsns.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\jaccess.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\localedata.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\nashorn.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\sunec.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\ext\zipfs.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\javaws.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\jce.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\jfr.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\jfxswt.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\jsse.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\management-agent.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\plugin.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\resources.jar;D:\工作磁盘\java环境\jdk1.8.0_181\jre\lib\rt.jar;D:\工作磁盘\yanwc_code\springboot-daily-crud-record\target\classes;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-starter-jdbc\2.1.7.RELEASE\spring-boot-starter-jdbc-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-starter\2.1.7.RELEASE\spring-boot-starter-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot\2.1.7.RELEASE\spring-boot-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-starter-logging\2.1.7.RELEASE\spring-boot-starter-logging-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\slf4j\jul-to-slf4j\1.7.26\jul-to-slf4j-1.7.26.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\zaxxer\HikariCP\3.2.0\HikariCP-3.2.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\slf4j\slf4j-api\1.7.26\slf4j-api-1.7.26.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-jdbc\5.1.9.RELEASE\spring-jdbc-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-beans\5.1.9.RELEASE\spring-beans-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-tx\5.1.9.RELEASE\spring-tx-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-starter-thymeleaf\2.1.7.RELEASE\spring-boot-starter-thymeleaf-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\thymeleaf\thymeleaf-spring5\3.0.11.RELEASE\thymeleaf-spring5-3.0.11.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\thymeleaf\thymeleaf\3.0.11.RELEASE\thymeleaf-3.0.11.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\attoparser\attoparser\2.0.5.RELEASE\attoparser-2.0.5.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\unbescape\unbescape\1.1.6.RELEASE\unbescape-1.1.6.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\thymeleaf\extras\thymeleaf-extras-java8time\3.0.4.RELEASE\thymeleaf-extras-java8time-3.0.4.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-starter-web\2.1.7.RELEASE\spring-boot-starter-web-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-starter-json\2.1.7.RELEASE\spring-boot-starter-json-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\fasterxml\jackson\core\jackson-databind\2.9.9\jackson-databind-2.9.9.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\fasterxml\jackson\core\jackson-core\2.9.9\jackson-core-2.9.9.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.9\jackson-datatype-jdk8-2.9.9.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.9\jackson-datatype-jsr310-2.9.9.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.9\jackson-module-parameter-names-2.9.9.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-starter-tomcat\2.1.7.RELEASE\spring-boot-starter-tomcat-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.22\tomcat-embed-core-9.0.22.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.22\tomcat-embed-el-9.0.22.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.22\tomcat-embed-websocket-9.0.22.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\hibernate\validator\hibernate-validator\6.0.17.Final\hibernate-validator-6.0.17.Final.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-web\5.1.9.RELEASE\spring-web-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-webmvc\5.1.9.RELEASE\spring-webmvc-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-aop\5.1.9.RELEASE\spring-aop-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-context\5.1.9.RELEASE\spring-context-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-expression\5.1.9.RELEASE\spring-expression-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-core\5.1.9.RELEASE\spring-core-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\spring-jcl\5.1.9.RELEASE\spring-jcl-5.1.9.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.1.0\mybatis-spring-boot-starter-2.1.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.1.0\mybatis-spring-boot-autoconfigure-2.1.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\mybatis\mybatis\3.5.2\mybatis-3.5.2.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\mybatis\mybatis-spring\2.0.2\mybatis-spring-2.0.2.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\commons-beanutils\commons-beanutils\1.8.0\commons-beanutils-1.8.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\commons-collections\commons-collections\3.2.1\commons-collections-3.2.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\commons-lang\commons-lang\2.5\commons-lang-2.5.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\net\sf\ezmorph\ezmorph\1.0.6\ezmorph-1.0.6.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\webjars\jquery\3.3.0\jquery-3.3.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\webjars\bootstrap\4.0.0\bootstrap-4.0.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\webjars\npm\popper.js\1.11.1\popper.js-1.11.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-configuration-processor\2.1.7.RELEASE\spring-boot-configuration-processor-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\mysql\mysql-connector-java\8.0.18\mysql-connector-java-8.0.18.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\baomidou\mybatis-plus-boot-starter\3.3.1\mybatis-plus-boot-starter-3.3.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\baomidou\mybatis-plus\3.3.1\mybatis-plus-3.3.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\baomidou\mybatis-plus-extension\3.3.1\mybatis-plus-extension-3.3.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\baomidou\mybatis-plus-core\3.3.1\mybatis-plus-core-3.3.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\baomidou\mybatis-plus-annotation\3.3.1\mybatis-plus-annotation-3.3.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\github\jsqlparser\jsqlparser\3.1\jsqlparser-3.1.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\org\springframework\boot\spring-boot-autoconfigure\2.1.7.RELEASE\spring-boot-autoconfigure-2.1.7.RELEASE.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\oracle\ojdbc\ojdbc8\19.3.0.0\ojdbc8-19.3.0.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\oracle\ojdbc\ucp\19.3.0.0\ucp-19.3.0.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\oracle\ojdbc\oraclepki\19.3.0.0\oraclepki-19.3.0.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\oracle\ojdbc\osdt_cert\19.3.0.0\osdt_cert-19.3.0.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\oracle\ojdbc\osdt_core\19.3.0.0\osdt_core-19.3.0.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\oracle\ojdbc\simplefan\19.3.0.0\simplefan-19.3.0.0.jar;D:\工作磁盘\java环境\maven\apache-maven-3.6.3-bin\repository\com\oracle\ojdbc\ons\19.3.0.0\ons-19.3.0.0.jar com.example.democrud.democurd.controller.JdbcUtil
数据库已知的用户: root@localhost
数据库的系统函数的逗号分隔列表: DATABASE,USER,SYSTEM_USER,SESSION_USER,PASSWORD,ENCRYPT,LAST_INSERT_ID,VERSION
数据库的时间和日期函数的逗号分隔列表: DAYOFWEEK,WEEKDAY,DAYOFMONTH,DAYOFYEAR,MONTH,DAYNAME,MONTHNAME,QUARTER,WEEK,YEAR,HOUR,MINUTE,SECOND,PERIOD_ADD,PERIOD_DIFF,TO_DAYS,FROM_DAYS,DATE_FORMAT,TIME_FORMAT,CURDATE,CURRENT_DATE,CURTIME,CURRENT_TIME,NOW,SYSDATE,CURRENT_TIMESTAMP,UNIX_TIMESTAMP,FROM_UNIXTIME,SEC_TO_TIME,TIME_TO_SEC
数据库的字符串函数的逗号分隔列表: ASCII,BIN,BIT_LENGTH,CHAR,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,CONCAT_WS,CONV,ELT,EXPORT_SET,FIELD,FIND_IN_SET,HEX,INSERT,INSTR,LCASE,LEFT,LENGTH,LOAD_FILE,LOCATE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH,MID,OCT,OCTET_LENGTH,ORD,POSITION,QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SPACE,STRCMP,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING_INDEX,TRIM,UCASE,UPPER
数据库供应商用于 'schema' 的首选术语: 
数据库URL: jdbc:mysql://127.0.0.1:3306/atguigudb?serverTimezone=UTC&nullCatalogMeansCurrent=true&RemarksReporting=true
是否允许只读:false
数据库的产品名称:MySQL
数据库的版本:8.0.29
驱动程序的名称:MySQL Connector/J
驱动程序的版本:mysql-connector-java-8.0.18 (Revision: fef2894d751d47223192b706977b4a5bc41e6be4)
数据库中使用的表类型
LOCAL TEMPORARY
SYSTEM TABLE
SYSTEM VIEW
TABLE
VIEW
--------
countries - TABLE - 
departments - TABLE - 
employees - TABLE - 
job_grades - TABLE - 
job_history - TABLE - 
jobs - TABLE - 
locations - TABLE - 
order - TABLE - 
regions - TABLE - 
--------
atguigudb - null - countries - TABLE - 
--------
atguigudb - null - countries - country_id - 1 - CHAR - 2 - 0 - 10 - 0 -  - null - 6 - 1 - NO
atguigudb - null - countries - country_name - 12 - VARCHAR - 40 - 0 - 10 - 1 -  - null - 120 - 2 - YES
atguigudb - null - countries - region_id - 4 - INT - 10 - 0 - 10 - 1 -  - null - 0 - 3 - YES
Process finished with exit code 0


main 方法启动类:在最后


本文都是以为 mysql 8.0 为主的 同时也注释了5.7的版本和参数;

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
弹性计算 安全 数据库
云上攻防-云服务篇&弹性计算&云数据库&实例元数据&控制角色&AK控制台接管
云上攻防-云服务篇&弹性计算&云数据库&实例元数据&控制角色&AK控制台接管
107 7
|
5月前
|
SQL 存储 关系型数据库
MySQL数据库——锁-表级锁(表锁、元数据锁、意向锁)
MySQL数据库——锁-表级锁(表锁、元数据锁、意向锁)
231 0
|
Oracle 关系型数据库 MySQL
数据库之-元数据 DatabaseMetaData 初学(一)
数据库之-元数据 DatabaseMetaData 初学(一)
183 0
|
Windows
ArcGIS:如何连接文件夹、修改元数据样式、建立个人地理数据库、复制移动文件?
ArcGIS:如何连接文件夹、修改元数据样式、建立个人地理数据库、复制移动文件?
373 0
|
存储 SQL 数据采集
SaaS厂商数据库设计(3)-租户元数据管理&数据管理
SaaS厂商设计中元数据管理以及逻辑视图方式下数据管理
681 2
SaaS厂商数据库设计(3)-租户元数据管理&数据管理
|
存储 监控 数据库
【DBMS 数据库管理系统】数据仓库 数据组织 ( 数据组织级别 | 元数据 | 粒度 | 分割 | 数据组织形式 )(二)
【DBMS 数据库管理系统】数据仓库 数据组织 ( 数据组织级别 | 元数据 | 粒度 | 分割 | 数据组织形式 )(二)
193 0
|
前端开发 数据库 数据库管理
【DBMS 数据库管理系统】数据仓库 数据组织 ( 数据组织级别 | 元数据 | 粒度 | 分割 | 数据组织形式 )(一)
【DBMS 数据库管理系统】数据仓库 数据组织 ( 数据组织级别 | 元数据 | 粒度 | 分割 | 数据组织形式 )(一)
347 0
|
Java 数据库连接 数据库
JDBC(九)DatabaseMetaData 数据库元数据
通过java.sql.DatabaseMetaData 接口,我们能获取到数据库的列表、列等信息。 DatabaseMetaData 接口包含了许多方法,这里值介绍常用的。
1622 0
|
14天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
29 1
下一篇
无影云桌面