Apache Ignite cache "IN" clause not working - java

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

Related

Nested SQL in #Query tag is not working properly

Suppose I have a table which contains all the accounts of user and type.
I want to make a Jpa Repository method which returns an array of total number of each type of user (USER, ADMIN, MASTER).
Here is how I did it in JpaRepository:
#Query(value="SELECT (SELECT COUNT(*) FROM account WHERE account_role='USER'),"
+ "(SELECT COUNT(*) FROM account WHERE account_role='ADMIN'),"
+ "(SELECT COUNT(*) FROM account WHERE account_role='MASTER')"
+ "FROM account LIMIT 1",
nativeQuery=true)
public List<Integer> getTotalAccountType();
The code executed fine, but the result wasn't what I expected.
Result:
[2]
Expected result: [2,10,30]
Any idea how would I use nested SQL with JPQL? Thank you in advance!
If repository method returns List of Integers it means that query result row contains an Integer value. But you expect to get sequence of Integers in one row.
You can get same result different way:
#Query(value="SELECT COUNT(*) FROM account WHERE account_role=?", nativeQuery=true)
public Integer getTotalAccountType(String role);
and then:
Integer userCount = repository.getTotalAccountType("USER");
Integer adminCount = repository.getTotalAccountType("ADMIN");
Integer masterCount = repository.getTotalAccountType("MASTER");
or if you have mapped entity:
create Pair<K,V> class with constructor Pair(K key, V value) or use it from any external library
repository method based on hql query
#Query(value="select new javafx.util.Pair(a.accountRole, count(a)) from Account a group by a.accountRole")
public List<Pair<String, Integer>> getRoleCountList();
convert repository result to a Map<String, Integer> in service
javafx.util.Pair<String, Integer> result = repository.getRoleCountList();
Map<String, Integer> map = result.stream().collect(Collectors.toMap(r-> r.getKey(), r-> r.getValue()));
Try returning Object[] rather than a List<Integer>. I think returning List<Integer> would indicate multiple rows of an Integer value are being returned, whereas you're getting back one row with multiple Intger columns.
From the resulting Object[] you would pull out the first value (indicating a row). This should be another Object[], which will have your values in the order returned.
You can also remove that last "FROM account LIMIT 1" line, as it has no bearing on the result.
I would recommend casting all of this to an object though. As seen here -
How to return a custom object from a Spring Data JPA GROUP BY query

Hibernate named query parameter IN list

I have found lots of answers for how to send a list parameter in to a query and check if a value is in that list but I'm trying to do the opposite - pass in the value and check if it's contained in a list in the object.
I have the following code to try to retrieve a Person using their username.
Person person = uniqueResult(namedQuery(Person.FIND_BY_USERNAME)
.setParameter("username", username).setMaxResults(1));
The username is contained in a list in the Person object.
#Column(name = "usernames")
#Convert(converter = PersonUsernameConvertor.class)
private List<String> usernames;
Is it possible to get the Person with the username parameter in their list with a NamedQuery or do I need something else? Below is what I have so far but it's not working, I'm guessing because the parameter value is on the left of the equation.
#NamedQuery(name = Person.FIND_BY_USERNAME,
query = "SELECT p from Person p WHERE :username IN p.usernames)
Example1:
#NamedQuery(name = Person.FIND_BY_USERNAME,
query = "SELECT p from Person p WHERE p.usernames in (:username)")
If usernames list contains only John and passing the parameter username with john, the above query works and returns the result.
Example2:
#NamedQuery(name = Person.FIND_BY_USERNAME,
query = "SELECT p from Person p WHERE p.usernames like CONCAT('%',:username,'%')")
If usernames list contains John,Joe and passing the parameter username with joe,the above query will check the list whether joe exists in the list or not.

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

Hibernate result list cast to get rows

Hello I had problem with iterate Hibernate ResultList
I had followed query that I got from external class:
queryContent = "select distinct c.identity, c.number, c.status, ctr.name, aab.paymentConditions.currency from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
And I must sum whole aab.paymentConditions.currency, check numbers of statutes and names.
I want to do this by iterate list of results:
Query q = session.createQuery(queryContent);
List result = q.list();
Long wholeCurrency, numberOfStatutes;
for(Object res : result){
//wholeCurrency += res.getColumnName?
}
My question is how to cast res Object to have possibility to get concrete column values? I had read about create map inside hibernate query but I don't know it is good practice to modyfied query string by adding
"new map(" prefix and then ")"
before from sql statement
Solution:
After All I decided to use map in my query. I modified my external query by adding hibernate map statement by replacing select by 'select new map(' and from by ') from'.
Additional thing is to add 'as' statement with name of key because without them column keys are integer.
So after all my query looks like follow:
"select new map( distinct c.identity, c.number, c.status as status, ctr.name as name, aab.paymentConditions.currency as currency ) from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
That was the most siutable solution for me, I tried with 'NEW com.example.MyClass' as Kostja suggested but in my case I didn't have control for incoming query so I can not rely on pernament constructor.
new List( select...
Is also interest but it also didn't tell me on with position I have my field that give me information.
If I understand correctly, you want to have a typed representation of your result without it being an entity itself. For this, you can use constructor queries:
"SELECT NEW com.example.MyClass( e.name, e.data) FROM Entity e"
MyClass has to have a matching constructor. Full qualification (com.example) is not mandatory AFAIK.
If you are using this query often, creating a view in the DB may be a good idea. You can map a view to an entity just as if it were a regular table, but please note that you cannot store changes to you data over a mapped view.
EDIT: Turns out, mapping to an unspecified Map is alright with Hibernate:
select new map( mother as mother, offspr as offspr, mate as mate )
As per http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch11.html#ql-select-clause
you can use
queryContent = "select new list(distinct c.identity, c.number, c.status, ctr.name, aab.paymentConditions.currency) from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
And you get List<List> as result.

Dynamic search using sql queries

I'm implementing dynamic search within my application, I have the following options to build a query.
String concatenation from the user input
Use multiple Queries, and pull the right query based on the user input
Use one query, use wild cards for the inputs not given by the user.
eg:
select * from A,B where a.id like nvl( {input}, '%')
and a.id = b.aid
and b.value like nvl({input2},'%');
Because id is a primary key I get the following error in the oracle when tried.
Firstly, for wildcard search you need to use the LIKE predicate, not =. Secondly, you can't use the LIKE predicate for numeric data, obviously. What you can do is this:
select * from A,B where ( a.id = {input} or {input} is null )...
A simple solution could be:
StringBuffer sqlSB = new StringBuffer("select * from A,B where a.id = b.aid ");
if(input!=null&&!input.equals("")){
sqlSB.append(" and a.id = ").append(input);
}
if(input2!=null&&!input2.equals("")){
sqlSB.append(" and b.value = '").append(input2).append("' ");
}

Categories

Resources