【问题标题】:Multiple, combined OR conditions in ORMLiteORMLite 中的多个组合 OR 条件
【发布时间】:2012-04-01 08:37:11
【问题描述】:

我喜欢这样的查询:

select data from table
 where (x > 1 and x < 100)
    or (x > 250 and x < 300)

在 ORMlite 中,可以使用以下代码:

final QueryBuilder<Data,Integer> qb = queryBuilder();
final Where<Data, Integer> w = qb.where();

w.or(
    w.gt("x", 1).and().lt("x", 100),
    w.gt("x", 250).and().lt("x", 300)
)

虽然如果事先知道条件并且在编码时很好,但我需要动态添加条件。

基本上那个方法public com.j256.ormlite.stmt.Where&lt;T,ID&gt; or(com.j256.ormlite.stmt.Where&lt;T,ID&gt; left, com.j256.ormlite.stmt.Where&lt;T,ID&gt; right, com.j256.ormlite.stmt.Where&lt;T,ID&gt;... others) 是不够的。 它需要另一个支持ArrayListWhere 条件的or 方法。

感谢您的任何建议。

【问题讨论】:

    标签: java ormlite


    【解决方案1】:

    虽然如果事先知道条件并且在编码时很好,但我需要动态添加条件。

    ORMLite Where.or(Where&lt;T, ID&gt; left, Where&lt;T, ID&gt; right, Where&lt;T, ID&gt;... others) 中有点语法技巧。当你打电话时:

    w.or(
        w.gt("x", 1).and().lt("x", 100),
        w.gt("x", 250).and().lt("x", 300)
    );
    

    or() 方法得到的是:

    w.or(w, w);
    

    你真的可以把它改写成:

    w.gt("x", 1).and().lt("x", 100);
    w.gt("x", 250).and().lt("x", 300);
    w.or(w, w);
    

    or 方法只使用参数来计算它需要从堆栈中弹出多少子句。当您调用 gtlt 等时,它会将项目推送到子句堆栈中。 and() 方法从堆栈中拉出 1 个项目,然后在将来获取另一个项目。我们进行这些语法修改是因为我们希望支持线性、链式和基于参数的查询:

    w.gt("x", 1);
    w.and();
    w.lt("x", 100);
    

    对比:

    w.gt("x", 1).and().lt("x", 100);
    

    对比:

    w.and(w.gt("x", 1), w.lt("x", 100));
    

    但这意味着您可以通过使用Where.or(int many) 方法极大地简化您的代码。所以在上面or的例子中也可以是:

    w.gt("x", 1).and().lt("x", 100);
    w.gt("x", 250).and().lt("x", 300);
    // create an OR statement from the last 2 clauses on the stack
    w.or(2);
    

    所以你根本不需要conditions 列表。您只需要一个计数器。所以你可以这样做:

    int clauseC = 0;
    for (int i : values) {
        if (i == 1) {
            w.le(C_PREIS, 1000);
            clauseC++;
        } else if (i == 2) {
            w.gt(C_PREIS, 1000).and().le(C_PREIS, 2500);
            clauseC++;
        } else if (i == 3) {
            w.gt(C_PREIS, 2500).and().le(C_PREIS, 5000);
            clauseC++;
        } else if (i == 4) {
            w.gt(C_PREIS, 5000).and().le(C_PREIS, 10000);
            clauseC++;
        } else if (i == 5) {
            w.gt(C_PREIS, 10000);
            clauseC++;
        }
    }
    // create one big OR(...) statement with all of the clauses pushed above
    if (clauseC > 1) {
        w.or(clauseC);
    }
    

    如果i 只能是 1 到 5,那么您可以直接使用 values.size() 并跳过 clauseC。请注意,如果我们只添加一个子句,那么我们可以完全跳过 OR 方法调用。

    哦,下面的语句不会起作用:

    target.or().raw(first.getStatement());
    

    因为targetfirst 是同一个对象。 first.getStatement() 转储整个 SQL WHERE 子句,我认为这不是你想要的。

    【讨论】:

    • 这太棒了!感谢您提供有关 ORMlite 的背景信息以及解释和帮助。愉快地消除代码和复杂性。谢谢!
    • 很高兴帮助塞巴斯蒂安。我真的很震惊@Jon 尝试回答 ORMLite 问题。我得到任何分数的唯一原因是 ORMLite 问题。他的回答通常很棒。 :-) 请务必编辑您的问题并删除或更正现在已过时的“已解决”部分。
    【解决方案2】:

    你明白声明中... 部分的含义吗?这意味着您可以传入一个 array(如果您只指定值,编译器将为您构造一个数组)。

    因此,如果您愿意,只需创建一个列表,然后将其转换为一个数组(除了 first 条件之外的所有条件),然后调用该方法。您可能很想创建一个静态方法来轻松完成最后一部分:

    public static <T, ID> void or(Where<T, ID> target,
                                  List<Where<T, ID>> conditions)
    {
        // TODO: Argument validation
        Where<T, ID> first = conditions.get(0);
        Where<T, ID> second = conditions.get(1);
        List<Where<T, ID>> rest = conditions.subList(2, conditions.size());
        // You'll to suppress a warning here due to generics...
        Where<T, ID>[] restArray = rest.toArray(new Where[0]);
        target.where(first, second, restArray);
    }
    

    【讨论】:

    • 啊,我怎么能错过。 ;) 谢谢乔恩。我试过你的例子,现在它说:cannot find symbol method or(com.j256.ormlite.stmt.Where&lt;T,ID&gt;,com.j256.ormlite.stmt.Where&lt;T,ID&gt;[])target.where 部分。
    • @SebastianRoth:好的,看起来我看错了签名——它是一个 third 参数。不过同样的想法。将编辑...
    • 谢谢乔恩,基本上你的建议是正确的。我看到这比它应该的要复杂得多。如果只有一个元素,或者只有两个等,这个想法将无法正常工作。我将编辑并将我的版本放在那里。这似乎需要对 ORMlite 进行更改。
    • @SebastianRoth:你可以轻松地调整这个实用方法来处理 1 个元素,并且它应该已经可以处理 2 个元素(通过一个空数组)。另一方面,我同意对 ORMlite 进行更改以使其更容易有用
    • 一些问题仍然存在,某些组合会创建无效查询。将尝试与 ORMLite 的 Gray 联系以讨论此问题。
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2023-04-08
    • 2020-05-13
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    相关资源
    最近更新 更多