简体   繁体   English

当 SQL 子句因退化情况需要“消失”时,有没有办法使用 @Bind 而不是 @Define?

[英]Is there a way to use @Bind instead of @Define when an SQL clause needs to "disappear" for a degenerate case?

Note: This example has been simplified heavily.注意:此示例已大大简化。

I started with a method like this:我从这样的方法开始:

private static final String QUERY_B = QUERY_A + " AND (foo = :bar) \n";

@SqlQuery(MASTER_QUERY + " AND " + QUERY_B)
public abstract Long doQueryB(@Bind("userId") String userId,
                              @Bind("bar") String bar);

The thing was, though, if bar was an empty string, I needed the entire clause to go away, eg as if it was just:然而,问题是,如果bar是一个空字符串,我需要整个子句消失,例如,好像它只是:

private static final String QUERY_B = QUERY_A + " \n";

So, I constructed a query that would simply insert "true" in that case, ie所以,我构造了一个查询,在这种情况下只会插入"true"

private static final String QUERY_B = QUERY_A + " AND true \n";

The idea was to generate a clause, either "true" or (foo = 123) , before passing the clause into the function:这个想法是在将子句传递给函数之前生成一个子句,无论是"true"还是(foo = 123)

private static final String QUERY_B = QUERY_A + " AND <clause> \n";

But this meant I had to use @Define , not @Bind :但这意味着我必须使用@Define ,而不是@Bind

@SqlQuery(MASTER_QUERY + " AND " + QUERY_B)
public abstract Long doQueryB(@Bind("userId") String userId,
                              @Define("clause") String clause);

And now this means this method is open to SQL injection.现在这意味着该方法对 SQL 注入开放。

I don't want to try to sanitize it myself ( Defense Option 4 ).我不想尝试自己对其进行消毒( 防御选项 4 )。

Is there a way to go back to using @Bind , without creating an entirely separately method, ie有没有办法回到使用@Bind而不创建一个完全单独的方法,

@SqlQuery(MASTER_QUERY + " AND " + QUERY_A)
public abstract Long doQueryB(@Bind("userId") String userId);

@SqlQuery(MASTER_QUERY + " AND " + QUERY_B)
public abstract Long doQueryB(@Bind("userId") String userId,
                              @Bind("bar") String bar);

...because there are several closely-related methods that would all need to be duplicated for the bar case, and on top of that, we expect more and more kinds of bar s to be introduced in the future, so that a large amount of methods would be need to be created, if we went that route. ...因为有几个密切相关的方法都需要为bar case 复制,除此之外,我们预计将来会引入越来越多的bar类型,以便大量如果我们走那条路,则需要创建许多方法。

I have implemented a similar logic in the past by using an OR clause that checks if the parameter needs to "disappear".过去,我通过使用 OR 子句检查参数是否需要“消失”来实现类似的逻辑。 So, in case of an empty string, your SQL could look like this:因此,在空字符串的情况下,您的 SQL 可能如下所示:

private static final String QUERY_B = QUERY_A + " AND (:bar = '' OR foo = :bar) \n";

The biggest advantage of this approach is that you can keep your method signature as is:这种方法的最大优点是您可以保持方法签名不变:

@SqlQuery(MASTER_QUERY + " AND " + QUERY_B)
public abstract Long doQueryB(@Bind("userId") String userId, @Bind("bar") String bar);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM