编写Java代码,使用druid实现血缘关系分析,包括表依赖关系和字段依赖关系
时间: 2024-02-27 13:56:57 浏览: 136
以下是使用Druid实现表依赖关系和字段依赖关系分析的Java代码示例:
```java
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.parser.SQLParserUtils;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.JdbcUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class DruidBloodLineageAnalyzer {
private DataSource dataSource;
public DruidBloodLineageAnalyzer(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 获取表依赖关系
* @param tableName 目标表名
* @return 依赖该表的所有表名列表
* @throws Exception
*/
public List<String> getTableDependency(String tableName) throws Exception {
List<String> result = new ArrayList<>();
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT sql_text FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%SELECT " + tableName + " %' AND COMMAND='Query'");
while (rs.next()) {
String sql = rs.getString("sql_text");
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
for (SQLStatement stmt : stmtList) {
stmt.accept(new SQLASTVisitorAdapter() {
public boolean visit(SQLSelectStatement selectStmt) {
SQLSelect select = selectStmt.getSelect();
SQLTableSource tableSource = select.getFrom();
String tableName = null;
if (tableSource instanceof SQLExprTableSource) {
tableName = ((SQLExprTableSource) tableSource).getName().getSimpleName();
} else if (tableSource instanceof SQLJoinTableSource) {
SQLJoinTableSource joinTableSource = (SQLJoinTableSource) tableSource;
SQLTableSource leftTableSource = joinTableSource.getLeft();
SQLTableSource rightTableSource = joinTableSource.getRight();
tableName = ((SQLExprTableSource) leftTableSource).getName().getSimpleName();
result.add(tableName);
tableName = ((SQLExprTableSource) rightTableSource).getName().getSimpleName();
}
result.add(tableName);
return true;
}
});
}
}
}
return result;
}
/**
* 获取字段依赖关系
* @param tableName 目标表名
* @param columnName 目标字段名
* @return 依赖该字段的所有字段名列表
* @throws Exception
*/
public List<String> getColumnDependency(String tableName, String columnName) throws Exception {
List<String> result = new ArrayList<>();
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT sql_text FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%SELECT " + columnName + " FROM " + tableName + " %' AND COMMAND='Query'");
while (rs.next()) {
String sql = rs.getString("sql_text");
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcUtils.MYSQL);
SQLStatement stmt = parser.parseStatement();
stmt.accept(new SQLASTVisitorAdapter() {
public boolean visit(SQLSelectStatement selectStmt) {
SQLSelect select = selectStmt.getSelect();
select.getQuery().accept(new SQLASTVisitorAdapter() {
public boolean visit(SQLSelectItem item) {
SQLExpr expr = item.getExpr();
if (expr instanceof SQLPropertyExpr) {
SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;
String tableName = propertyExpr.getOwner().getSimpleName();
String columnName = propertyExpr.getName();
result.add(columnName);
} else if (expr instanceof SQLIdentifierExpr) {
SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;
String columnName = identifierExpr.getName();
result.add(columnName);
}
return true;
}
});
return true;
}
});
}
}
return result;
}
}
```
以上代码中,`getTableDependency`方法可以获取依赖目标表的所有表名列表,`getColumnDependency`方法可以获取依赖目标字段的所有字段名列表。该代码基于Druid的SQL Parser实现,可以解析目标数据库的SQL语句,从而获取表依赖关系和字段依赖关系。需要注意的是,该代码中使用的是MySQL数据库的语法,如果使用其他数据库需要相应地修改代码。
阅读全文