簡體   English   中英

如何在 java 的全局 DbConnection 中使用准備好的 sql 語句?

[英]How to use a prepared sql statement in a global DbConnection in java?

對於學校,我有一個 Java 項目和幾個 Maven 庫。

對於我們的數據庫連接,我創建了一個“全局”連接文件,在這個文件中我有一些基本的 select、更新和刪除方法,您可以從其他文件中調用這些方法,例如: select(query). 我從這個問題中得到了這個代碼: https://stackoverflow.com/a/42587131/11870062

現在的問題; 我們需要一個准備好的語句,我如何在保持 select 方法全局可用的同時實現它。

這是 DbConnection class:

public ArrayList<ArrayList<Object>> Select(String query){

    try{
        Statement statement = this.connection.createStatement();
        ResultSet rs = statement.executeQuery(query);

        ResultSetMetaData metaData = rs.getMetaData();

        ArrayList<ArrayList<Object>> result = new ArrayList<>();

        while (rs.next()){

            ArrayList<Object> row = new ArrayList<Object>();

            for (int i = 1; i <= metaData.getColumnCount(); i++){
                String strColumnName = metaData.getColumnName(i);
                Object columnValue = rs.getObject(i);
                row.add(columnValue);

            }
            result.add(row);
        }
        return result;

    }catch (SQLException e){
        e.printStackTrace();
    }

    return null;
}

正如一些評論中所建議的,您的方法違反了 Java 安全准則,原因有很多,最重要的是:

  • 它不執行和檢查輸入
  • 這是 SQL 注入攻擊的大門,因為它不控制對數據庫執行哪種類型的查詢。

但是,如果這只是一項學校作業,我可以幫助您使用PreparedStatemnt來實現它。
這個想法是您假設調用者知道輸入查詢中包含的參數數量並為其提供確切的值數量。
基於此,我能想到的最簡單的實現是以下一個:

public ArrayList<Map<String, Object>> performGenericParameterizedQuery(String queryWithParameters, 
    Object ... values) {
    
    ArrayList<Map<String, Object>> result = new ArrayList<>();
    
    try(PreparedStatement ps = this.connection.preparedStatement(queryWithParameters)) {
        
        for(int i=0; i<values.length; i++) {
            ps.setObject(i+1, values[i]);
        }
        
        ResultSet rs = ps.executeQuery();
        
        ResultSetMetaData metaData = rs.getMetaData();

        while (rs.next()){

            Map<String, Object> row = new HashMap<>();

            for (int i = 1; i <= metaData.getColumnCount(); i++){
                String strColumnName = metaData.getColumnName(i);
                Object columnValue = rs.getObject(i);
                row.put(columnValue, strColumnName);
            }
            result.add(row);
        }
    
    }catch (SQLException e){
        e.printStackTrace();
    }

    return result;
}

老實說,我實際上並沒有編譯或測試過這種方法。 但我只是想告訴你如何“一般”使用PreparedStatement 我假設您的 class 中有可用的connection實例(您可能將其作為 Singleton 或僅在您的類的特定init方法中准備),另外您應該添加所有必需的導入。
您會注意到我使用了 Map 列表,而不是您選擇的結構,我認為它更清晰,更適合此目的。
此外,正如我所做的那樣,我總是建議將您的語句包裝在 try-with-resource 塊上,因此一旦執行從塊中退出並且不會出現,它將自動關閉(與ResultSet一起)是任何資源泄漏。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM