0

私は次のPreparedStatementを持っています:

  PreparedStatement statement = conn.prepareStatement("Select * from foo 
          where foo.age ? ? AND foo.children ? ?")

私は怠惰で、複数のクエリを書くのが好きではないので、今私が何をしようとしているのかを説明します。終了すると、ステートメントは次のようになります。

Select * from foo where foo.age >= 42 AND foo.children <= 3

また

Select * from foo where foo.age = 42 AND foo.children = 3

明確でない場合は、複数のトークンを連続して置き換えることができるようにしたいのですが、最初のトークンはたまたま修飾子(equals、greater、lessなど)であり、その後のトークンはたまたまリテラル(3、 17、「スティーブ」など)。私の質問は、これは可能であり、もしそうなら、これをどのように達成できるかということです。

4

4 に答える 4

4

tokenではなくvalue?を表すため、これを行うことはできません。明らかに、一部のトークン (つまり、リテラル) は値を表しますが、これらの場合でも、値を表すリテラルではなく、値自体を直接表します。(これは設計の意図的な要素です。パラメーター化されたクエリの目的は、パラメーターが「漏れ」、単一の値以外のものとして解釈されるのを防ぐことであるためです。)?


編集して追加:私が働いている場所では、JDBC をラップしてトランザクションなどを処理するカスタム フレームワークがあるため、通常PreparedStatementは直接処理する必要はありません。そのフレームワークには、次のようなメソッドがあります。

public <T> Iterator<T> executeQuery(ConverterFromResultSetToT<T> converter,
                                     String query, Map<String, Object> params)
{
    // . . . modify query, replacing any instances of $!{paramKey} with the
    //       corresponding value from params -- this allows arbitrary SQL code
    //       to be injected, in the rare cases that that's necessary

    // . . . modify query, replacing any instances of ${paramKey} with '?' and
    //       adding the corresponding value from params to an array -- we use
    //       this much more often

    // . . . create PreparedStatement with the resulting query

    // . . . set parameters of PreparedStatement from aforemented array

    // . . . run PreparedStatement; wrap result in an Iterator<T>; and return
}

しかし、これをたくさん行うことが予想される場合にのみ、そのようなことをお勧めします. 私たちはそのフレームワークに多大な労力を注ぎました。これは信じられないほど便利ですが、大量のコードでもあります。


ドキュメントが何を暗示しているかにかかわらず、 を作成するコストはPreparedStatementそれほど高くないことに注意してください。PreparedStatement実際に同じクエリを何度も実行していない限り、毎回再作成しても大したことではありません。そのため、独自のコードを作成する意思がある限り、ドロップイン演算子の組み込みサポートは実際には必要ありません。

于 2012-10-10T19:20:05.910 に答える
2

これはできません。aのパラメータはPreparedSatement値のみであり、演算子やテーブル名などではありません。

ここで、上記の特定のクエリに対して、次のことを実行できます。

select * from foo where age > ? and age < ? 

次に、で42400あなたはage>=42年を取得し、で4242あなたはage = 42

于 2012-10-10T19:19:01.687 に答える
2

次のような回避策があります。

String query = "Select * from foo where foo.age @ @ AND foo.children @ @";

//write code here to manipulate your query string using
query = query.replaceFirst("@", "=");
query = query.replaceFirst("@", "42");
query = query.replaceFirst("@", "=");
query = query.replaceFirst("@", "3");

Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query );

上記のように使用するreplaceFirst場合は、値を割り当てていることに注意してくださいfrom left to right

于 2012-10-10T19:23:33.830 に答える
0
String firstOperator = ">="
String secondOperator = "<="

PreparedStatement statement = conn.prepareStatement("Select * from foo 
          where foo.age "+firstOperator+" ? AND foo.children "+secondOperator+" ?");

statement.setInt(1,42);
statement.setInt(2,3);

とにかく、私はそれが非常にエレガントなことだとは思いません。「複数のクエリを書かない」というのは、賢明な設計目標ではないようです。

于 2012-10-10T19:34:53.593 に答える