美文网首页
从数据库连接的DatabaseMetaData中获取表结构信息

从数据库连接的DatabaseMetaData中获取表结构信息

作者: neko_11 | 来源:发表于2020-07-07 14:48 被阅读0次

前言

我们在开发过程中,有时需要读取表结构信息。但是如何处理不同数据库的兼容性问题呐?我们可以从数据库连接的元数据中获取我们需要的信息。

属性说明

  • getTables
TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
TABLE_TYPE String => 表类型。典型的类型是 "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。
REMARKS String => 表的解释性注释
TYPE_CAT String => 类型的类别(可为 null)
TYPE_SCHEM String => 类型模式(可为 null)
TYPE_NAME String => 类型名称(可为 null)
SELF_REFERENCING_COL_NAME String => 有类型表的指定 "identifier" 列的名称(可为null)
REF_GENERATION String => 指定在 SELF_REFERENCING_COL_NAME 中创建值的方式。这些值为 "SYSTEM"、"USER" 和 "DERIVED"。(可能为null)
  • getPrimaryKeys
TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
COLUMN_NAME String => 列名称
KEY_SEQ short => 主键中的序列号
PK_NAME String => 主键的名称(可为 null)
  • getIndexInfo
NON_UNIQUE int => 非唯一索引
INDEX_QUALIFIER String => 索引目录(可为 null)  
INDEX_NAME String => 索引的名称  
TYPE short => 索引类型  
ORDINAL_POSITION short => 在索引列顺序号  
COLUMN_NAME String => 列名  
ASC_OR_DESC String => 列排序顺序:升序还是降序  
CARDINALITY int => 基数  
  • getColumns
TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
COLUMN_NAME String => 列名称
DATA_TYPE int => 来自 java.sql.Types 的 SQL 类型
TYPE_NAME String => 数据源依赖的类型名称,对于 UDT,该类型名称是完全限定的
COLUMN_SIZE int => 列的大小。对于 char 或 date 类型,列的大小是最大字符数,对于 numeric 和 decimal 类型,列的大小就是精度。
BUFFER_LENGTH 未被使用。
DECIMAL_DIGITS int => 小数部分的位数
NUM_PREC_RADIX int => 基数(通常为 10 或 2)
NULLABLE int => 是否允许使用 NULL。
columnNoNulls - 可能不允许使用 NULL 值
columnNullable - 明确允许使用 NULL 值
columnNullableUnknown - 不知道是否可使用 null
REMARKS String => 描述列的注释(可为 null)
COLUMN_DEF String => 默认值(可为 null)
SQL_DATA_TYPE int => 未使用
SQL_DATETIME_SUB int => 未使用
CHAR_OCTET_LENGTH int => 对于 char 类型,该长度是列中的最大字节数
ORDINAL_POSITION int => 表中的列的索引(从 1 开始)
IS_NULLABLE String => "NO" 表示明确不允许列使用 NULL 值,"YES" 表示可能允许列使用 NULL 值。空字符串表示没人知道是否允许使用 null 值。
SCOPE_CATLOG String => 表的类别,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为null)
SCOPE_SCHEMA String => 表的模式,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为null)
SCOPE_TABLE String => 表名称,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null)
SOURCE_DATA_TYPE short => 不同类型或用户生成 Ref 类型、来自 java.sql.Types 的 SQL 类型的源类型(如果 DATA_TYPE 不是 DISTINCT 或用户生成的 REF,则为null)

工具方法

DbUtils

public class DbUtils {

    private static final Logger LOG = LoggerFactory.getLogger(DbUtils.class);

    private DbUtils() {
    }

    private static final String MYSQL = "MYSQL";
    private static final String ORACLE = "ORACLE";
    private static final String HANA = "HANA";
    private static final String SQLSERVER = "SQLSERVER";
    private static final String H2 = "H2";
    private static final String POSTGRESQL = "POSTGRESQL";
    private static final String ZENITH = "ZENITH";

    private static final String SCHEMA = "";

    public static List<Table> getTables(DbConfig config) {
        List<Table> list = new ArrayList<>();
        try (Connection connection = getConnection(config)) {
            DatabaseMetaData metaData = connection.getMetaData();
            if (metaData == null) {
                return list;
            }
            String[] types = {"TABLE"};
            ResultSet tables = metaData.getTables(null, SCHEMA, "%", types);
            while (tables.next()) {
                String tableName = tables.getString("TABLE_NAME");
                String tableRemarks = tables.getString("REMARKS");
                Table table = new Table(tableName, tableRemarks);
                ResultSet primaryKeys = metaData.getPrimaryKeys(null, SCHEMA, tableName);
                while (primaryKeys.next()) {
                    String primaryKey = primaryKeys.getString("COLUMN_NAME");
                    table.setPrimaryKey(primaryKey);
                }
                if (LOG.isInfoEnabled()) {
                    String a = String.format("tableName: %-30s primaryKey: %-30s remarks: %-1s", table.getName(), table.getPrimaryKey(), table.getRemarks());
                    LOG.info(a);
                    LOG.info("======================================================================================================================");
                    String b = String.format("%-30s | %-12s | %-1s", "index_name", "unique", "columns");
                    LOG.info(b);
                    LOG.info("----------------------------------------------------------------------------------------------------------------------");
                }
                // 获取索引
                table.setIndexList(getIndex(metaData, table));
                if (LOG.isInfoEnabled()) {
                    LOG.info("======================================================================================================================");
                    String c = String.format("%-30s | %-12s | %-6s | %-6s | %-8s | %-13s | %-18s | %-1s", "name", "type", "size", "digits", "nullable", "autoIncrement", "defaultValue", "remarks");
                    LOG.info(c);
                    LOG.info("----------------------------------------------------------------------------------------------------------------------");
                }
                // 获取列
                table.setColumnList(getColumn(metaData, table));
                LOG.info("#################################################################################################################################");
                list.add(table);
            }
            return list;
        } catch (Exception e) {
            return list;
        }
    }

    private static List<Index> getIndex(DatabaseMetaData metaData, Table table) {
        String tableName = table.getName();
        List<Index> list = new ArrayList<>();
        if (metaData == null) {
            return list;
        }
        Map<String, List<String>> indexMap = new HashMap<>(16);
        Map<String, Index> map = new HashMap<>(16);
        try {
            ResultSet indexInfo = metaData.getIndexInfo(null, SCHEMA, tableName, false, false);
            while (indexInfo.next()) {
                String indexName = indexInfo.getString("INDEX_NAME");
                String columnName = indexInfo.getString("COLUMN_NAME");
                boolean unique = !indexInfo.getBoolean("NON_UNIQUE");
                short ordinalPosition = indexInfo.getShort("ORDINAL_POSITION");
                if (!map.containsKey(indexName)) {
                    map.put(indexName, new Index().setName(indexName).setUnique(unique));
                }
                // 暂存索引列
                List<String> indexList = indexMap.computeIfAbsent(indexName, k -> new ArrayList<>());
                indexList.add(ordinalPosition - 1, columnName);
            }

            map.forEach((indexName, index) -> {
                List<String> indexList = indexMap.get(indexName);
                index = index.setFields(StringUtils.join(indexList, ","));
                if (LOG.isInfoEnabled()) {
                    String a = String.format("%-30s | %-12s | %-1s", index.getName(), index.isUnique(), index.getFields());
                    LOG.info(a);
                }
                list.add(index);
            });
            return list;
        } catch (Exception e) {
            return list;
        }
    }

    private static List<Column> getColumn(DatabaseMetaData metaData, Table table) {
        String tableName = table.getName();
        List<Column> list = new ArrayList<>();
        if (metaData == null) {
            return list;
        }
        try {
            ResultSet columns = metaData.getColumns(null, "%", tableName, "%");
            while (columns.next()) {
                String columnName = columns.getString("COLUMN_NAME");
                String columnType = columns.getString("TYPE_NAME");
                int dataSize = columns.getInt("COLUMN_SIZE");
                int digits = columns.getInt("DECIMAL_DIGITS");
                boolean nullable = columns.getBoolean("NULLABLE");
                boolean autoIncrement = columns.getBoolean("IS_AUTOINCREMENT");
                String defaultValue = columns.getString("COLUMN_DEF");
                if (defaultValue == null) {
                    defaultValue = "";
                }
                String remarks = columns.getString("REMARKS");
                if (LOG.isInfoEnabled()) {
                    String a = String.format("%-30s | %-12s | %-6s | %-6s | %-8s | %-13s | %-18s | %-1s", columnName, columnType, dataSize, digits, nullable, autoIncrement, defaultValue, remarks);
                    LOG.info(a);
                }
                list.add(new Column(columnName, columnType, dataSize, digits, nullable, autoIncrement, defaultValue, remarks));
            }
            return list;
        } catch (Exception e) {
            return list;
        }
    }

    private static Connection getConnection(DbConfig config) throws SQLException, ClassNotFoundException {
        Class.forName(config.getDriver());
        String dbType = getDbType(config.getUrl());
        Properties properties = new Properties();
        properties.setProperty("user", config.getUsername());
        properties.setProperty("password", config.getPassword());
        switch (dbType) {
            case MYSQL:
                properties.setProperty("remarks", "true");
                properties.setProperty("useInformationSchema", "true");
                break;
            case ORACLE:
            default:
                properties.setProperty("remarks", "true");
                break;
        }
        return DriverManager.getConnection(config.getUrl(), properties);
    }

    private static String getDbType(String url) {
        if (url.startsWith("jdbc:h2")) {
            return H2;
        } else if (url.startsWith("jdbc:oracle")) {
            return ORACLE;
        } else if (url.startsWith("jdbc:mysql")) {
            return MYSQL;
        } else if (url.startsWith("jdbc:sqlserver")) {
            return SQLSERVER;
        } else if (url.startsWith("jdbc:sap")) {
            return HANA;
        } else if (url.startsWith("jdbc:postgresql")) {
            return POSTGRESQL;
        } else if (url.startsWith("jdbc:zenith")) {
            return ZENITH;
        }
        return "UNKNOWN";
    }
}

实体

DbConfig 数据库连接信息

public class DbConfig {

    public DbConfig() {
    }

    public DbConfig(String driver, String url, String username, String password) {
        this.driver = driver;
        this.url = url;
        this.username = username;
        this.password = password;
    }

    private String driver;
    private String url;
    private String username;
    private String password;

    public String getDriver() {
        return driver;
    }

    public DbConfig setDriver(String driver) {
        this.driver = driver;
        return this;
    }

    public String getUrl() {
        return url;
    }

    public DbConfig setUrl(String url) {
        this.url = url;
        return this;
    }

    public String getUsername() {
        return username;
    }

    public DbConfig setUsername(String username) {
        this.username = username;
        return this;
    }

    public String getPassword() {
        return password;
    }

    public DbConfig setPassword(String password) {
        this.password = password;
        return this;
    }
}

Table 表对象

 public class Table {

    /**
     * 表名称
     */
    private String name;
    /**
     * 注释
     */
    private String remarks;
    /**
     * 主键字段
     */
    private String primaryKey;

    private List<Index> indexList;
    private List<Column> columnList;

    public Table() {
    }

    public Table(String name, String remarks) {
        this.name = name;
        this.remarks = remarks;
    }

    public Table(String name, String remarks, String primaryKey) {
        this.name = name;
        this.remarks = remarks;
        this.primaryKey = primaryKey;
    }

    public String getName() {
        return name;
    }

    public Table setName(String name) {
        this.name = name;
        return this;
    }

    public String getRemarks() {
        return remarks;
    }

    public Table setRemarks(String remarks) {
        this.remarks = remarks;
        return this;
    }

    public String getPrimaryKey() {
        return primaryKey;
    }

    public Table setPrimaryKey(String primaryKey) {
        this.primaryKey = primaryKey;
        return this;
    }

    public List<Index> getIndexList() {
        return indexList;
    }

    public Table setIndexList(List<Index> indexList) {
        this.indexList = indexList;
        return this;
    }

    public List<Column> getColumnList() {
        return columnList;
    }

    public Table setColumnList(List<Column> columnList) {
        this.columnList = columnList;
        return this;
    }

    @Override
    public String toString() {
        return "Table{" +
                "name='" + name + '\'' +
                ", remarks='" + remarks + '\'' +
                ", primaryKey='" + primaryKey + '\'' +
                ", indexList=" + indexList +
                ", columnList=" + columnList +
                '}';
    }

Index 表索引

public class Index {

    /**
     * 索引名称
     */
    private String name;
    /**
     * 是否唯一索引
     */
    private boolean unique;
    /**
     * 索引列 逗号分隔
     */
    private String fields;

    public String getName() {
        return name;
    }

    public Index setName(String name) {
        this.name = name;
        return this;
    }

    public boolean isUnique() {
        return unique;
    }

    public Index setUnique(boolean unique) {
        this.unique = unique;
        return this;
    }

    public String getFields() {
        return fields;
    }

    public Index setFields(String fields) {
        this.fields = fields;
        return this;
    }

    @Override
    public String toString() {
        return "Index{" +
                ", name='" + name + '\'' +
                ", unique=" + unique +
                ", fields='" + fields + '\'' +
                '}';
    }
}

Column 表格列

public class Column {

    /**
     * 字段名
     */
    private String name;
    /**
     * 字段类型
     */
    private String type;
    /**
     * 字段长度
     */
    private int size;
    /**
     * 小数
     */
    private int digits;
    /**
     * 可否为空
     */
    private boolean nullable;
    /**
     * 是否自增
     */
    private boolean autoIncrement;
    /**
     * 默认值
     */
    private String defaultValue;
    /**
     * 备注
     */
    private String remarks;

    public Column() {
    }

    public Column(String name, String type, int size, int digits, boolean nullable, boolean autoIncrement, String defaultValue, String remarks) {
        this.name = name;
        this.type = type;
        this.size = size;
        this.digits = digits;
        this.nullable = nullable;
        this.autoIncrement = autoIncrement;
        this.defaultValue = defaultValue;
        this.remarks = remarks;
    }

    public String getName() {
        return name;
    }

    public Column setName(String name) {
        this.name = name;
        return this;
    }

    public String getType() {
        return type;
    }

    public Column setType(String type) {
        this.type = type;
        return this;
    }

    public int getSize() {
        return size;
    }

    public Column setSize(int size) {
        this.size = size;
        return this;
    }

    public int getDigits() {
        return digits;
    }

    public Column setDigits(int digits) {
        this.digits = digits;
        return this;
    }

    public boolean isNullable() {
        return nullable;
    }

    public Column setNullable(boolean nullable) {
        this.nullable = nullable;
        return this;
    }

    public boolean isAutoIncrement() {
        return autoIncrement;
    }

    public Column setAutoIncrement(boolean autoIncrement) {
        this.autoIncrement = autoIncrement;
        return this;
    }

    public String getDefaultValue() {
        return defaultValue;
    }

    public Column setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
        return this;
    }

    public String getRemarks() {
        return remarks;
    }

    public Column setRemarks(String remarks) {
        this.remarks = remarks;
        return this;
    }

    @Override
    public String toString() {
        return "Column{" +
                "name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", size=" + size +
                ", digits=" + digits +
                ", nullable=" + nullable +
                ", autoIncrement=" + autoIncrement +
                ", defaultValue='" + defaultValue + '\'' +
                ", remarks='" + remarks + '\'' +
                '}';
    }
}

相关文章

  • 从数据库连接的DatabaseMetaData中获取表结构信息

    前言 我们在开发过程中,有时需要读取表结构信息。但是如何处理不同数据库的兼容性问题呐?我们可以从数据库连接的元数据...

  • MetaData

    MetaData 元数据 指数据库中 库、表、列的定义信息。 DataBaseMetaData 数据库元数据 通...

  • MySQL 连接查询超全详解

    1 作用 在数据库中join操作被称为连接,作用是能连接多个表的数据(通过连接条件),从多个表中获取数据合并在一起...

  • 数据库设计

    数据库连接 表结构

  • dbeaver 7.1.3版本编辑表结构

    dbeaver 连接后不能编辑表结构?找到原因了 数据库连接编辑 中 选择 advanced 先进的才可以 编辑表...

  • 从数据连接获取表信息

    从数据连接获取表信息 适配所有的数据库,如:oracle、mysql等。里面用到的异常请删除即可。 需要引入hut...

  • DatabaseMetaData类

    DatabaseMetaData类 DatabaseMetaData类是java.sql包中的类,利用它可以获取我...

  • JDBC

    建立数据库连接 简化连接不同数据库,将连接数据库信息存储到文件中 通过获取驱动连接数据库,可同时获得多个驱动 执行...

  • MySQL的JOIN用法

    数据库中的JOIN称为连接,连接的主要作用是根据两个或多个表中的列之间的关系,获取存在于不同表中的数据。连接分为三...

  • 任务2.5 项目总结汇报

    任务内容 一、GIF效果图 2、数据库表结构 三、ADO.NET查询数据库的流程(1)获取连接字符串;(2) 运用...

网友评论

      本文标题:从数据库连接的DatabaseMetaData中获取表结构信息

      本文链接:https://www.haomeiwen.com/subject/mvmaqktx.html