1

getAllIDs()データベース内の特定のテーブルのIDを取得するために使用されるメソッド' 'があります。私のプロジェクトでは多くの方法で使用されています。

public static int[] getAllIDs (String TableName, String WhereClause, String trxName)
    {
        ArrayList<Integer> list = new ArrayList<Integer>();
        StringBuffer sql = new StringBuffer("SELECT ");
        sql.append(TableName).append("_ID FROM ").append(TableName);
        if (WhereClause != null && WhereClause.length() > 0)
            sql.append(" WHERE ").append(WhereClause);
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try
        {
            pstmt = DB.prepareStatement(sql.toString(), trxName);
            rs = pstmt.executeQuery();
            while (rs.next())
                list.add(new Integer(rs.getInt(1)));
        }
}

Whereclauseは、クエリの条件付き部分です。このwhereclauseが原因でSQLインジェクションの可能性があります。したがって、このメソッドを変更して、プリペアドステートメントのパラメーター設定を使用してパラメーターを設定する必要があります。私が直面した問題は、' getAllIDs()'各whereclauseのパラメーターの数がわからないためです。

パラメータはwhereclauseごとに異なり、任意の数にすることができます。一部のクラスでは、パラメーターは3になり、一部のクラスでは2になり、データ型が異なります。では、setstring()、setint()などをどのように使用できますか。投稿したコードで説明してください。

4

5 に答える 5

5

PreparedStatementBinderメソッドに追加の引数を渡します。

public interface PreparedStatementBinder {
    /**
     * Binds all the arguments to the given prepared statement
     */
    public void bindArguments(PreparedStatement statement) throws SQLException;
}

呼び出し元は、where 句 ( など"foo = ? and bar = ?") と、このインターフェイスのインスタンス( など) を渡す必要があります。

new PreparedStatementBinder() {
    @Override
    public void bindArguments(PreparedStatement statement) throws SQLException {
        statement.setString(1, theFoo);
        statement.setInt(2, theBar);
    }
}
于 2012-09-07T10:27:34.333 に答える
2

これを行うには、いくつかの方法があります。WhereClause簡単な方法は、パラメーターの名前と値を保持するマップのように動作させることです。次に、キーに基づいて準備済みステートメント テンプレートを定義し、それに値を入力します。AND/OR キーワードを使用して where 句を結合したり、句ごとに異なる演算子を使用したりする場合は、よりスマートなデータ構造が必要になる場合があります: = / < / > / NOT / IS NULL など、これらすべてが動的に行われます。

より洗練されたライブラリを利用できる場合、Hibernate またはその他の ORM ツールの Criteria API は、この種のユースケースに非常に適しています。

于 2012-09-07T10:28:21.820 に答える
1

オブジェクト リレーショナル マッパー (ORM) やクエリ ジェネレーターなどを構築しているようです。

もしそうなら、問題に対する既存の解​​決策を使用することを検討してください。

JPA または Hibernate Criteria API を検討してください。それらは醜いですが、包括的です。プログラムによるクエリ ジェネレータは他にも多数ありますが、そのすべてが ORM に関連付けられているわけではありません。

この車輪を再発明しないでください。今は簡単に見えるかもしれませんが、設計が非常に複雑で扱いにくくなるまで、限界にぶつかり続けることになります。

于 2012-09-07T10:33:14.237 に答える
0

多分私はあなたをすべて間違っているかもしれませんが、私はあなたの声明から推測したことに基づいて解決策を提案しています. 次のようにWhere-Clauseパラメーターをオプションにします

public static int[] getAllIDs (String tableName, String... whereClause, String trxName) 

そして、それらが表示された場合は、次のように設定します

 for(String param:whereClause)
  {
       pst.setParameter("Param-name",param);
  }
于 2012-09-07T10:21:57.750 に答える
0

ほとんどの人は、Hibernate や JPA のような完全な ORM ソリューションを提案しています。この 1 つのクエリだけに必要な場合は、これらのいずれかを統合するのに多少の労力がかかりますが、これが SQL インジェクションの対象となる唯一のクエリではなく、一部/ほとんど/すべてでセットアップを再利用できると推測しますアプリ内のクエリ。

ただし、手っ取り早い解決策は、条件が数個しかない場合に、条件のバリエーションごとにメソッドを作成することです。各メソッドは、必要なパラメーターの正確なタイプを受け入れ、これらの引数を prepareStatement にバインドする方法を知っています。テーブル名、txn 名などを渡され、SELECT 句と FROM 句を返す (これらのメソッドによって呼び出される) クラスにファクトリ メソッドが存在する可能性があります。

選択したソリューションに関係なく、getAllIds() の呼び出し元を変更する必要があります。

于 2012-09-07T13:53:48.560 に答える