PreparedStatement多次替换没有逗号分隔符

时间:2012-10-10 19:17:29

标签: java sql prepared-statement

我有以下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

OR

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

如果不清楚我希望能够连续替换多个令牌,其中第一个令牌恰好是限定符(等于,更大,更少等),并且后面的令牌恰好是文字(3,17, “史蒂夫”,等等)。我的问题是这是否可能,如果是这样,如何实现呢?

4 个答案:

答案 0 :(得分:4)

您无法执行此操作,因为?不代表令牌,而是。显然,一些标记(即文字)代表值,但即使对于这些标记,?也直接表示值本身,而不是文字 - 也 - 代表 - 值。 (这是设计的一个有意的元素,因为参数化查询的目的是防止参数“泄漏”并被解释为单个值以外的其他东西。)


编辑添加:在我工作的地方,我们有一个自定义框架,它包装了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都不是什么大问题。因此,只要您愿意为此编写自己的代码,就不需要内置支持drop-in运算符。

答案 1 :(得分:2)

这不可能。 PreparedSatement中的参数只能是值,而不是运算符,表名等。

现在,对于上面的特定查询,您可以执行以下操作:

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

然后使用42400获得age>=42年,使用4242获得age = 42

答案 2 :(得分: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

答案 3 :(得分: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);

无论如何,我认为这不是一件非常优雅的事情。 “不写多个查询”似乎不是一个明智的设计目标。