Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
397 views
in Technique[技术] by (71.8m points)

java - Multiple, combined OR conditions in ORMLite

I like to have a query like this:

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

In ORMlite, that's possible using this code:

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

While thats great if one knows the conditions beforehand & at the time of coding, I need the conditions to be dynamically added.

Basically that method public com.j256.ormlite.stmt.Where<T,ID> or(com.j256.ormlite.stmt.Where<T,ID> left, com.j256.ormlite.stmt.Where<T,ID> right, com.j256.ormlite.stmt.Where<T,ID>... others) is not enough. It needs another or method that supports a ArrayList of Where conditions.

Thanks for any suggestions.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

While thats great if one knows the conditions beforehand & at the time of coding, I need the conditions to be dynamically added.

In ORMLite Where.or(Where<T, ID> left, Where<T, ID> right, Where<T, ID>... others) is a bit of a syntax hack. When you call:

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

What the or() method gets is:

w.or(w, w);

You really could rewrite it as:

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

The or method there is only using the arguments to count how many clauses it needs to pop off of the stack. When you call gt and lt and others, it pushes items on a clause stack. The and() method pulls 1 item off the stack and then takes another item in the future. We do these syntax hacks because we want to support linear, chained, and argument based queries:

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

versus:

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

versus:

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

But this means that you have the power to simplify your code immensely by using the Where.or(int many) method. So in the or example above can also be:

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

So you don't need the conditions list at all. All you need is a counter. So you could do something like:

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

If i can only be 1 to 5 then you can just use values.size() and skip the clauseC. Notice that if we are only adding one clause then we can skip the OR method call entirely.

Oh, and the following statement will not work:

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

because target and first are the same object. first.getStatement() dumps the entire SQL WHERE clause which I don't think is what you want.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...