jOOQ - query builder with IN predicate - java

I am trying to build a query like this:
List<Integer> ids = ...
String query = DSL.select(TABLE.SOMETHING).from(TABLE).where(TABLE.ID.in(ids)).
getSQL();
But I am not able to get the generated query with the values, just the placeholders.
I tried DSL.inline(ids) but it doesnt' work.
How can I do this?
I am using jOOQ 3.4.2.
Thanks for the help.
UPDATE:
Seems I can do this with:
Configuration configuration = new DefaultConfiguration();
configuration.set(SQLDialect.DERBY);
Settings settings = new Settings()
.withStatementType(StatementType.STATIC_STATEMENT);
configuration.set(settings);
DSLContext create = DSL.using(configuration);
String query = create.select(TABLE.SOMETHING).from(TABLE).where(TABLE.ID.in(ids)).getSQL();
If someone can confirm that is th right way, thanks.

You cannot inline a list with jOOQ's DSL.inline() because if you could, the semantics of such a value would be that of a list/array literal in the database, not of a list of individual values.
Correct way to use DSL.inline():
Here's one correct way to pass a list of inlined values to the Field.in(Field<?>...):
List<Integer> ids = ...
String query = DSL.using(configuration) // Use a Configuration or at least a SQLDialect!
.select(TABLE.SOMETHING)
.from(TABLE)
.where(TABLE.ID.in(ids.stream().map(DSL::inline).collect(toList())))
.getSQL();
Inline all bind values on a per-getSQL() basis:
Use Query.getSQL(ParamType)
List<Integer> ids = ...
String query = DSL.using(configuration)
.select(TABLE.SOMETHING)
.from(TABLE)
.where(TABLE.ID.in(ids))
.getSQL(ParamType.INLINED);
Inline all bind values on a per-Configuration basis:
The solution you've mentioned in your question edit is valid as well, of course:
List<Integer> ids = ...
Configuration configuration = new DefaultConfiguration();
configuration.set(new Settings().withStatementType(StatementType.STATIC_STATEMENT));
String query = DSL.using(configuration)
.select(TABLE.SOMETHING)
.from(TABLE)
.where(TABLE.ID.in(ids))
.getSQL();

Related

DynamoDb IN operator in Java

I have a working DynamoDb query, but I'm trying to add an IN operator and can't figure out the syntax for the FilterExpression.
pages is a List<Integer> and I have an attribute in my table which is an Integer, so I'm doing something like this
attrValues.put(":pages", AttributeValue.fromL(pages.stream()
.map(i->AttributeValue.fromN(i.toString()))
.collect(Collectors.toList())));
String filterExpression = "in(originalPageNumber, :pages)"
final QueryRequest.Builder queryBuilder = QueryRequest.builder()
.tableName(Parameters.addPrefix(TABLE_NAME))
.keyConditionExpression(keyConditionExpression)
.expressionAttributeNames(attrNameAlias)
.expressionAttributeValues(attrValues)
.filterExpression(filterExpression);
(this is not the complete code. Just the relevant parts)
But it doesn't like my syntax at all. I've tried originalPageNumber in :pages and other variations as well.
Update
Other things I tried
Tried setting :pages to
final String pagesStr = pages.stream().map(i -> i.toString()).collect(Collectors.joining(", ", "(", ")"));
final AttributeValue pagesAttr = AttributeValue.fromS(pagesStr);
attrValues.put(":pages", pagesAttr);
or AttributeValue(S=(1, 2))
I then got rid of :pages altogether and just set filterExpression to in(originalPageNumber, (1, 2)). Still no luck.
Also tried originalPageNumber in (1, 2)
Try it like this:
String filterExpression = "originalPageNumber IN (:pages)"
:pages would need to be a comma separated list of values. Which should essentially map to:
String filterExpression = "originalPageNumber IN (1,2,3,7,9)"

Query dsl - Looping through a list to create OR predicates

How do I dynamically create "OR" predicates if I have a List<List<String>>
I am using query dsl and spring data.
QOrder order = QOrder.order;
JPQLQuery<Order> query = from(order);
query.where(order.status.eq("ready"));
List<List<String>> filterTypes;
This is what I am trying to do:
for(List<String> types : filterTypes) {
query.where(order.type.in(types));
}
So the result should be something like
select * from order o where o.status='ready' and (o.type in(t1,t2) or o.type in(t3,t4))
To directly answer your question: assuming you're using a relatively modern version of QueryDSL, you should be able to use a BooleanBuilder:
QOrder order = QOrder.order;
SQLQuery<Order> query = from(order);
query.where(order.status.eq("ready"));
// Example data
List<List<String>> filterTypes = ImmutableList.of(
ImmutableList.of("t1", "t2"),
ImmutableList.of("t3", "t4"));
BooleanBuilder builder = new BooleanBuilder();
for (List<String> types : filterTypes) {
builder.or(order.type.in(types));
}
query.where(builder);
Backing up, assuming your actual application data model is similar to the example you provided, this:
o.type in (t1,t2) or o.type in (t3,t4)
Is equivalent to:
o.type in (t1,t2,t3,t4)
You could translate your List<List<String>> into List<String> and do your type query update once:
QOrder order = QOrder.order;
SQLQuery<Order> query = from(order);
query.where(order.status.eq("ready"));
// Example data
List<List<String>> filterTypes = ImmutableList.of(
ImmutableList.of("t1", "t2"),
ImmutableList.of("t3", "t4"));
List<String> flatFilterTypes = filterTypes.stream().flatMap(List::stream).collect(Collectors.toList());
query.where(order.type.in(flatFilterTypes));
I suspect that your database's query optimizer would do the same thing for either query (you'd have to check a query execution plan to be sure), but it'd probably be more clear what's going on if you did simplified the query on the Java side rather than relying on the database query optimizer.

Apache Ignite cache "IN" clause not working

What I want to do is
final String query = "select userName from users where userId in
(?) and isActive = 1";
SqlFieldsQuery sql = new SqlFieldsQuery(query);
List<Long> userIds = new ArrayList<Long>();
userIds.add(140l);
userIds.add(245l);
sql.setArgs(userIds.toArray());
List<List<?>> rsList = usersCache.query(sql).getAll();
. It is not giving the desired result. It is returning only one result
instead of two.
Please suggest
It's impossible to pass an array as an argument for in. You can rewrite your query to use a join instead. It will look as follows:
select u.userName from users u
join table (userId bigint=?) t on u.userId=t.userId
where u.isActive=1
Another thing you should take into account is that SqlFieldsQuery.setArgs(...) takes a vararg as an argument. So, to prevent your array from being unfolded, you should add a cast to Object:
sql.setArgs((Object)userIds.toArray());

How to use OR queries in greenDAO?

I have a query like:
Select * from table where user = 'user1' or city = 'delhi';
I know how to do it for single user but I am not getting how can I use or in following query.
dao.queryBuilder()
.where(UserDao.Properties.UserId.eq(userId1))
.list();
For Version 3.2.+, here is an example to use a combination of Where() and WhereOr() conditions. The below is a hypothetical query to select all items:
That have the tags 'paint', 'emulsion'
That belong to a specific Category
Excluding a particular Sub Category
The Where() method takes exactly one query condition and the WhereOr() can take multiple query conditions (as many as the number of properties in the Dao Class), separated by comma
String catgId = "AB12545";
String excludeSubCatgId = "SAB09990";
DaoSession daoSession = ((App) getApplication()).getDaoSession();
List<Item> = daoSession.getItemDao().queryBuilder()
.where(ItemDao.Properties.CategoryId.eq(catgId))
.where(ItemDao.Properties.SubCategory.notEq(excludeSubCatgId))
.whereOr(ItemDao.Properties.ItemTagCloud.like("%paint%"),
ItemDao.Properties.ItemTagCloud.like("%emulsion%"))
.orderDesc(ItemDao.Properties.ItemPrice)
.list();
In order to use or conditions in greenDAO, you have to use or method in QueryBuilder object.
Example:
QueryBuilder<User> qb = dao.queryBuilder();
qb.where(UserDao.Properties.UserId.eq(userId1), qb.or(UserDao.Properties.City.eq("delhi")));
List<User> users = qb.list();
For more details, see the "Queries" section in greenDAO documentation.
Try this:
QueryBuilder<User> qb = dao.queryBuilder();
qb.whereOr(UserDao.Properties.UserId.eq(userId1),
UserDao.Properties.City.eq("delhi"));
List<User> users = qb.list();

Select distinct values from MongoDB array using Java

I want to get a list of unique values from a List field called categories.
I am using Java and MongoDB. Most of the examples and docs I can see seem to suggest I need to do something like what I have below:
public static List<String> listCategories(String input) {
Datastore ds = Dao.instance().getDatabase();
BasicDBObject dbObject=new BasicDBObject("categories", input);
DBCollection dBCollection = ds.getCollection(Product.class);
List<String> categories = dBCollection.distinct("categories",dbObject);
return categories;
}
However when I test it using this code:
#Test
public void testListCategories(){
List<String> categories = Product.listCategories("S");
Assert.assertTrue(categories.size() > 0);
}
The test fails even though I know there are categories that start with S (have also tried a few others just to be sure).
Is it even possible to do this, if so do you have any pointers?
Thanks
BasicDBObject dbObject=new BasicDBObject();
dbObject.append(categories", input);
Now it will be like a where condition,
DBCollection dBCollection = ds.getCollection(Product.class);
List<String> categories = dBCollection.distinct("categories",dbObject);
The test fails even though I know there are categories that start with S (have also tried a few others just to be sure).
You need to perform a regex match using the $regex operator on the categories field to find distinct categories that start with a particular input.
Your updated code should look like:
BasicDBObject like = new BasicDBObject("$regex",
java.util.regex.Pattern.compile("^"+input,
Pattern.CASE_INSENSITIVE));
BasicDBObject query = new BasicDBObject("categories", like);
List<String> categories = dBCollection.distinct("categories",query);

Categories

Resources