表的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); } } }