注意:此示例已经过大量简化。
我开始使用这样的方法:
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
个到将来会被引入,以便在我们走这条路的时候需要创建大量的方法。
答案 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);