2

私は、ユーザーがさまざまな方法で大きなルックアップテーブルをクエリできる小さなWebベースのツールを作成しています。小さなツールなので、JSP/サーブレットを使用しています。

ルックアップテーブルには、次のような定義があります。

column1 | column2 | column3 | 日付| ユーザー| カウント

ユーザーは、列の値または範囲でクエリを実行できます。また、結果は特定の列で並べ替えることができます。テーブルには数十万のレコードがあり、急速に成長しているため、私はOracleのROWNUMを使用しており、結果の小さなサブセットのみを返します。

ユーザーから検索条件を取得するフォームページがあります。一連の条件に基づいてクエリを生成します。次に例を示します。

query = "SELECT * FROM mytable WHERE 1=1 "
if(searchCriteria1 != "")
    query += "AND column1='searchCriteria1' "
if(searchCriteria2 != "")
    query += "AND column2='searchCriteria2' "
if(searchCriteria2 != "")
    query += "AND column2='searchCriteria2' "
if(searchCriteria3 != "")
    query += "AND column3='searchCriteria3' "
if((searchCriteria4 != "") && (searchCriteria5 != ""))
    query += "AND date>='searchCriteria4' AND date<='searchCriteria5' "
etc...

(これは単純化された擬似コードです)

並べ替えは、最初の結果ページが表示された後に処理されます。ユーザーはそのページの列ヘッダーをクリックして、その列で並べ替えます。これは、ポストバックを実行し、データベースにクエリを実行します。基本的に、私は上記と同じコードを実行しますが、最後にこれを使用します。

if(sortColumn1)
    query += "ORDER BY column1"
if(sortColumn2)
    query += "ORDER BY column2"
if(sortColumn3)
    query += "ORDER BY column3"

したがって、ご想像のとおり、私のクエリ構築コードは非常に長く、これらすべての異なる条件があります。これを行うためのより良い方法に関する提案はありますか?

4

5 に答える 5

3

文字列の連結はSQLにとって最良の選択ではありません。最善の方法は、 QueryDSLまたはJOOQを使用して、OOの方法で実行することです。私はQueryDSLに精通しています。こちらの例をご覧ください。

SQLQuery query = new SQLQueryImpl(connection, dialect); 
query.from(myTable);

BooleanBuilder wheres = new BooleanBuilder();

if(notBlank(searchCriteria1))
   wheres.and(myTable.column1.eq(searchCriteria1));
if(notBlank(searchCriteria2))
   wheres.and(myTable.column2.eq(searchCriteria2));
if(notBlank(searchCriteria4) && notBlank(searchCriteria5))
   wheres.andAllOf(myTable.date.goe(searchCriteria4),  myTable.date.loe(searchCriteria5));  //you may want to use myTable.date.between(...)

if (...) {
   query.orderBy(myTable.column1.asc());
} else if (...){
   query.orderBy(myTable.column2.asc());
}

query.limit(100); //it is good to limit a result
query.list(myTable.all());

SQLインジェクションに関しては、クエリエンジンは、SQLの構築中に、名前付きパラメータで引数をラップします。

于 2012-10-25T22:29:17.937 に答える
2

Stringまず、クエリに単純なものを使用しないでください。SQLインジェクション(悪意のあるユーザーが脆弱なシステムを混乱させる非常に簡単な方法)からユーザーを保護するPreparedStatementを使用する必要があります。

if()... else if()...第二に、入力が本当に複雑な場合、ブロックを回避するためにできることはあまりありません。あなたの方法は、本来よりもはるかに多くのことをしているように見えます。ユーザーが実行したいクエリのタイプに基づいて、さまざまなメソッドを呼び出すことを検討してください。私は多くのDAOを実装しましたが、句に行をif追加する場合、ブロック内のこれらすべてのnullチェックを回避する方法はありません。ANDWHERE

ただし、確実に実行できることの1つは、ほとんどのクエリprivate static final Stringを疑問符付きの定数で記述し、パラメータを(?)にし、ユーザー入力に基づいて必要な他の基準を追加し、PreparedStatementそこから直接構築することです。を作成したらPreparedStatement、さまざまなsetterコマンドを使用して、それらを入力することができます?。これにより、コードがかなり整理されます。

于 2012-10-25T22:37:56.890 に答える
1

文字列の連結を使用して、ユーザーが入力したデータをクエリに入力することは決してありません。クエリで名前付きパラメータまたは位置パラメータを使用し、パラメータを渡す必要があります。

于 2012-10-25T22:21:06.763 に答える
0

並べ替えを行うためにバックエンドにリクエストを送信するのは良い考えではないと思います。jsには、テーブルを並べ替えるためのプラグインがたくさんあります。これを使用できます。

于 2012-10-25T22:16:24.477 に答える
0

単純化した観点から

タイプするすべての列がわかっている場合は、配列とテーブルを使用して、このコードをよりデータ駆動型にすることができます。

于 2012-10-25T22:16:41.660 に答える