【问题标题】:Java SQL safely check if column existsJava SQL 安全地检查列是否存在
【发布时间】:2017-04-20 18:44:38
【问题描述】:

我需要动态 SQL,它接受来自用户的表和列名并在查询中使用它们。现在我用

public Object doSearch(String table, List<String> columns) {
//... some logic
String.format("SELECT %s from %s", String.join(", ", columns), table");
//... some execution and return
}

来源不受信任,因此我想做一个表名和列名的白名单,但该列表发生了变化。有效表的列表严格来说是my_schema 上的表列表,而有效列的列表严格来说是该特定表上的列。

我搜索了 SO 并得到了一个看起来像这样的解决方案:

private boolean validate(String tableName, List<String> columnNames) throws SQLException {
    return tableExist(tableName) && columnNames.stream().allMatch(cn -> columnExistsOnTable(tableName, cn));
}
private boolean tableExist(String tableName) throws SQLException {
    try (ResultSet rs = connection.getMetaData().getTables(null, schema, tableName, null)) {
        while (rs.next()) {
            String tName = rs.getString("TABLE_NAME");
            if (tName != null && tName.equals(tableName)) {
                return true;
            }
        }
    }
    return false;
}

private boolean columnExistsOnTable(String tableName, String columnName) {
    try (ResultSet rs = connection.getMetaData().getColumns(null, schema, tableName, columnName)) {
        while (rs.next()) {
            String tName = rs.getString("COLUMN_NAME");
            if (tName != null && tName.equals(tableName)) {
                return true;
            }
        }
    } catch (SQLException sqle) {
        return false;
    }
    return false;
}

这样安全正确吗?

【问题讨论】:

  • 我觉得可以参考this post。您实际上需要获取数据库定义才能解析它并找到您需要的对象。该项目可能会帮助您独立于数据源工作。

标签: java postgresql jdbc


【解决方案1】:

对于这些方法中的每一个,您可以在初始化方法中执行一次并缓存表/列名,这样您就不必每次都进行数据库检查......像这样:

private Map<String, Set<String>> tableColNames = new HashMap();


    private void initCache(){
       // build the cache


  // get all tables 
   // get all columns
   // add tables and columns to the map 
}


private boolean tableExist(String tableName) throws SQLException {
    return tableColNames.containsKey(tableName);
}

private boolean columnExistsOnTable(String tableName, String columnName) {
   if(tableExist(tableName)){
     return   tableColNames.get(tableName).contains(columnName);
   } else {
     return false;
   }

}
// could make a method for checking a list of Strings too...
// return tableColNames.get(tableName).containsAll(columnName);

https://docs.oracle.com/javase/7/docs/api/index.html?java/sql/ResultSetMetaData.html

【讨论】:

    猜你喜欢
    • 2016-12-29
    • 1970-01-01
    • 2021-03-12
    • 2015-04-01
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多