当 SQL 子句需要 "disappear" 用于退化情况时,有没有办法使用 @Bind 而不是 @Define ?

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

注意:此示例已大大简化。

我从这样的方法开始:

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 的种类越来越多以后会引入,如果我们走那条路,将需要创建大量的方法。

我过去通过使用 OR 子句来检查参数是否需要 "disappear" 来实现类似的逻辑。因此,如果是空字符串,您的 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);