java获取数据库的所有表结构和索引等元数据

表的POJO:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: jinyang
 * @date: 2020-06-28 12:33
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Table {

    String tableName;

    String tableComment;

    List<Column> columnList = new ArrayList<>();

}

表中列的POJO:

import lombok.Data;

/**
 * @author: jinyang
 * @date: 2020-06-28 14:40
 **/
@Data
public class Column {

    String name;

    String type;

    String length;

    String decimalDigits;

    boolean notNull;

    boolean primary;

    String comment;

}

索引的POJO:

import lombok.Data;
import org.apache.commons.lang3.StringUtils;

/**
 * @author: jinyang
 * @date: 2020-06-28 15:22
 **/
@Data
public class Index {

    String tableName;

    String indexName;

    boolean unique;

    String params;

    public void addParams(String param) {
        if (StringUtils.isBlank(params)) {
            params = param;
        } else {
            params = params + "," + param;
        }
    }
}

一个抽象接口,实现了2种获取数据库schema元数据的方式,一种直接连库导入,另一种通过sql脚本批量导入(大家按需取用)

import java.util.ArrayList;
import java.util.List;

/**
 * @author: jinyang assembled
 * @date: 2020-06-29 20:24
 **/
public interface AssembledDatabaseMetadata {

    List<Table> tables = new ArrayList<>();

    List<Index> indices = new ArrayList<>();

    default List<Table> getTables() {
        return tables;
    }

    default List<Index> getIndices() {
        return indices;
    }

}

第一种方式,连数据库直接获取所有表结构和索引信息

import lombok.SneakyThrows;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * @author: jinyang
 * @date: 2020-06-28 19:51
 **/
public class AssembledFromDatabase implements AssembledDatabaseMetadata {

    private String driver = "com.mysql.cj.jdbc.Driver";

    @SneakyThrows
    public AssembledFromDatabase(String url, String user, String pwd) {
        Class.forName(driver);
        Properties props = new Properties();
        props.setProperty("user", user);
        props.setProperty("password", pwd);
        props.setProperty("remarks", "true");
        props.setProperty("useInformationSchema", "true");
        Connection connection = DriverManager.getConnection(url, props);
        DatabaseMetaData metaData = connection.getMetaData();
        ResultSet tableRs = metaData.getTables(connection.getCatalog(), connection.getCatalog(), "%", new String[]{"TABLE"});
        while (tableRs.next()) {
            String tableName = tableRs.getString("TABLE_NAME");

            List<Column> columns = new ArrayList<>();
            Table table = new Table(tableName, tableRs.getString("REMARKS"), columns);
            String primaryColumn = null;
            ResultSet idxRs = metaData.getIndexInfo(connection.getCatalog(), connection.getCatalog(), tableName, false, false);
            while (idxRs.next()) {
                String indexName = idxRs.getString("INDEX_NAME");
                if ("PRIMARY".equals(indexName)) {
                    primaryColumn = idxRs.getString("COLUMN_NAME");
                    continue;
                }
                List<Index> exist = indices.stream().filter(o -> o.getTableName().equals(tableName) && o.getIndexName().equals(indexName)).collect(Collectors.toList());
                Index index;
                if (exist != null && exist.size() > 0) {
                    index = exist.get(0);
                    index.setParams(index.getParams() + "," + idxRs.getString("COLUMN_NAME"));
                } else {
                    index = new Index();
                    index.setTableName(tableName);
                    index.setIndexName(indexName);
                    index.setUnique(!idxRs.getBoolean("NON_UNIQUE"));
                    index.setParams(idxRs.getString("COLUMN_NAME"));
                    indices.add(index);
                }
            }
            ResultSet columnRs = metaData.getColumns(connection.getCatalog(), connection.getCatalog(), tableName, "%");
            while (columnRs.next()) {
                Column column = new Column();
                column.setName(columnRs.getString("COLUMN_NAME"));
                column.setType(columnRs.getString("TYPE_NAME"));
                column.setLength(columnRs.getString("COLUMN_SIZE"));
                column.setDecimalDigits(columnRs.getString("DECIMAL_DIGITS"));
                column.setNotNull(!columnRs.getBoolean("NULLABLE"));
                column.setPrimary(column.getName().equals(primaryColumn));
                column.setComment(columnRs.getString("REMARKS"));
                columns.add(column);
            }
            tables.add(table);
        }
    }
}

第二种方式,通过SQL脚本获取所有表结构和索引信息(第二种方式还是有瑕疵,适合datagrip导出的sql脚本,就当给大家提供思路了,主要还是推荐第一种,省力方便)

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import jinyang.project.work.util.FileUtil;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: jinyang
 * @date: 2020-06-29 20:23
 **/
public class AssembledFromSqlFile implements AssembledDatabaseMetadata {

    static Pattern idxPattern = Pattern.compile("CREATE INDEX.*?;");

    static Pattern uniqueIdxPattern = Pattern.compile("CREATE UNIQUE INDEX.*?;");

    public AssembledFromSqlFile(String sqlFiles) {
        List<String> sqls = FileUtil.readFiles(sqlFiles);

        // 解析SQL
        for (String sql : sqls) {
            assembleTable(tables, sql);
            assembleIndex(indices, idxPattern.matcher(sql));
            assembleIndex(indices, uniqueIdxPattern.matcher(sql));
        }
    }

    private static void assembleTable(List<Table> tables, String sql) {
        Table table = new Table();
        SQLStatementParser parser = new MySqlStatementParser(sql);
        SQLStatement sqlStatement = parser.parseStatement();
        List<SQLObject> sqlObjects = sqlStatement.getChildren();

        for (SQLObject sqlObject : sqlObjects) {

            if (sqlObject instanceof SQLExprTableSource) {
                SQLName sqlName = ((SQLExprTableSource) sqlObject).getName();
                table.setTableName(sqlName.getSimpleName());
            } else if (sqlObject instanceof SQLColumnDefinition) {
                SQLColumnDefinition columnDefinition = ((SQLColumnDefinition) sqlObject);
                Column column = new Column();
                column.setName(columnDefinition.getNameAsString());
                column.setType(columnDefinition.getDataType().getName());
                List<SQLExpr> arguments = columnDefinition.getDataType().getArguments();
                if (!CollectionUtils.isEmpty(arguments)) {
                    column.setLength(((SQLIntegerExpr) arguments.get(0)).getNumber().toString());
                }
                column.setNotNull(columnDefinition.getConstraints().stream().anyMatch(o->o instanceof SQLNotNullConstraint));
                column.setPrimary(columnDefinition.getConstraints().stream().anyMatch(o->o instanceof SQLColumnPrimaryKey));
                if (columnDefinition.getComment() != null) {
                    column.setComment((String) ((SQLCharExpr) columnDefinition.getComment()).getValue());
                }
                table.getColumnList().add(column);
            }
        }
        tables.add(table);
    }

    private static void assembleIndex(List<Index> indices, Matcher matcher) {
        while (matcher.find()) {
            Index index = new Index();
            String indexSql = matcher.group();
            SQLStatementParser indexSqlParser = new MySqlStatementParser(indexSql);
            SQLStatement indexSqlStatement = indexSqlParser.parseStatement();
            List<SQLObject> indexSqlObjects = indexSqlStatement.getChildren();
            for (SQLObject indexSqlObject : indexSqlObjects) {
                if (indexSqlObject instanceof SQLIdentifierExpr) {
                    index.setIndexName(((SQLIdentifierExpr) indexSqlObject).getName());
                } else if (indexSqlObject instanceof SQLExprTableSource) {
                    index.setTableName(((SQLExprTableSource) indexSqlObject).getName().getSimpleName());
                } else if (indexSqlObject instanceof SQLSelectOrderByItem) {
                    index.addParams(((SQLIdentifierExpr) ((SQLSelectOrderByItem) indexSqlObject).getExpr()).getName());
                }
            }
            if (matcher.pattern() == uniqueIdxPattern) {
                index.setUnique(true);
            }
            indices.add(index);
        }
    }
}

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值