当SQL子句需要"消失时,有没有办法使用@Bind而不是@Define?#34;对于堕落的案例?

时间:2018-02-20 16:59:15

标签: java sql dao jdbi

注意:此示例已经过大量简化。

我开始使用这样的方法:

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);

但事情是,如果bar是一个空字符串,我需要整个条款消失,例如就像它只是:

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

所以,我构建了一个查询,在这种情况下简单地插入"true"

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

我们的想法是在将子句传递给函数之前生成一个子句"true"(foo = 123)

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

但这意味着我必须使用@Define,而不是@Bind

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

现在这意味着此方法对SQL注入开放。

我不想自己尝试对其进行消毒(Defense Option 4)。

有没有办法可以回到使用@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);

...因为有几个密切相关的方法都需要为bar案例重复,而且最重要的是,我们期望越来越多的bar个到将来会被引入,以便在我们走这条路的时候需要创建大量的方法。

1 个答案:

答案 0 :(得分:2)

我过去使用OR子句实现了类似的逻辑,该子句检查参数是否需要“消失”。因此,如果是空字符串,您的SQL可能如下所示:

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

此方法的最大优点是您可以按原样保留方法签名:

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