Here municipalities parameter can be null. but IN clause doesnt work for null. If there was only one paramater i.e municipalities, I could have handle this in java level. but there is another condition in OR, which has to be executed.
List<Municipality> municipalities = myDao.findAll(); // returns empty list
em.createQuery("SELECT p FROM Profile p JOIN p.municipality m WHERE m IN (:municipalities) OR m.city = :city")
.setParameter("municipalities", municipalities)
.setParameter("city", city)
.getResultList();
So how to do this? Can we handle null in JPA IN clause. like if it is null then dont execute that condition
you can modify the query
String sql="";
if(municipalities!=null){
sql="SELECT p FROM Profile p JOIN p.municipality m WHERE m IN (:municipalities) OR m.city = :city"
}
else
{
sql="SELECT p FROM Profile p JOIN p.municipality m WHERE m.city = :city"
}
List<Municipality> municipalities = myDao.findAll(); // returns empty list
em.createQuery(sql)
.setParameter("municipalities", municipalities)
.setParameter("city", city)
.getResultList();
Related
Following code getting only projectId = 1 records but also wish account null ones. I am missing something?
#Query(value = "SELECT M FROM Message M WHERE M.account IS NULL OR M.account.project.id = 1")
List<Message> findMessages();
this one gets true result.
#Query(value = "SELECT M FROM Message M WHERE M.account IS NULL")
List<Message> findMessages();
also true result
#Query(value = "SELECT M FROM Message M WHERE M.account IS NULL OR M.account.id = 1")
List<Message> findMessages();
Thank you.
I think it is JPQL null issue with join.
This is alternative solution , fixed and applied for my other complex script.
Anyway appreciated if explain the base reason of this issue.
#Query(value = "SELECT M FROM Message M LEFT JOIN M.account A WHERE M.account IS NULL OR A.project.id = 1")
List findMessages();
When I try this I get the proper JSON as a result, but it takes a lot of time:
Criteria c = sessionFactory.getCurrentSession().createCriteria(User.class);
List<User> users = c.list();
List<User> specialUsers = new ArrayList<>();
for (User user : users) {
List<Perm> userPerms = user.getProfile().getPerms();
for (Perm perm : userPerms) {
if (perm.getId().equals(SPECIAL_ID)) {
specialUsers.add(user);
}
}
}
return specialUsers;
and the JSON is like:
[{"id":111,"name":"Name111"},{"id":222,"name":"Name222"}]
In attempt to improve performance I tried code below. In SQL app the results are OK, a few records of users:
String sql = "SELECT u.id, u.name FROM app.user u inner join app.perms p where u.profile = p.profile AND p.right= :rightId";
List<User> specialUsers= (List<User>)sessionFactory.getCurrentSession()
.createSQLQuery(sql)
.setParameter("rightId", SPECIAL_ID)
.list();
return specialUsers;
Now the 'JSON' however looks like this:
[[111,"Name111"],[222,"Name222"]]
I tried several things, like select *, criteria.add(Restrictions...) but to no effect. What I noticed is that in the first case specialUsers.toString returns proper data, in the second case it returns meaningless Strings like Ljava.lang.Object;#23e1469f.
Any hints how to solve this?
I managed to solve this in this way, may not be perfect:
// get ids of all special users
String sql = "SELECT u.id FROM app.user u inner join app.perms p where u.profile = p.profile AND p.right= :rightId";
List<Integer> intIds = sessionFactory.getCurrentSession()
.createSQLQuery(sql)
.setParameter("rightId", SPECIAL_ID)
.list();
// convert to long values
List<Long> longIds = intIds.stream()
.mapToLong(Integer::longValue)
.boxed().collect(Collectors.toList());
// get all special users
Criteria c = sessionFactory
.getCurrentSession()
.createCriteria(User.class)
.add(Restrictions.in("id", longIds));
List<User> specialUsers = c.list();
return specialUsers;
}
I'm wondering if is possible to make this kind of evaluation with collections like the query isn't working in my project at a class named query as follow:
#NamedQueries(value = {
#NamedQuery(
name = "Foo.getBarList",
query = "select f from Foo f where (:barlist is null or f.barlist.id in (:barslist)) " )})
from this both post:
FROM Foo WHERE Id = :id AND (:barlist is null or Bar in (:barlist))
JPA where clause any
Hibernate HQL Query : How to set a Collection as a named parameter of a Query?
I guess the problem was the id in query so I remove and the error stop, just change this:
"select f from Foo f where (:barlist is null or f.barlist in (:barslist)) "
instead of in HQL you can check
if(barlist==null){
//query=FROM Foo WHERE Id = :id
}else{
//query=FROM Foo WHERE Id = :id AND Bar in :barlist
// query.setParameterList(:barlist",<list object>)
}
I need a single named query that fulfills below both named query conditions only by setting the Query parameter.
Named Query, to fetch record where "softwareVersion" is null OR softwareVersion matched with the list.
#NamedQuery(name = "getIPDetectionDetailsForPanIndia",
query = "select cssc.css.sapId,
cssc.css.hostName,
cssc.cssGoldenConfiguration.category,
cssc.cssGoldenConfiguration.parameter,
cssc.cssGoldenConfiguration.vendor,
cssc.recommendedValue,
cssc.actualValue,
cssc.cssGoldenConfiguration.id,
cssc.cssGoldenConfiguration.information,
cssc.css.softwareVersion,
jioc.name,
cssc.cssGoldenConfiguration.impact,
cssc.cssGoldenConfiguration.command
from CssComplianceDetail cssc
join cssc.css c
left join c.cluster club
left join clus.jiocenter jioc
where cssc.cssGoldenConfiguration.impact in (:impactType)
and cssc.cssGoldenConfiguration.category in (:category)
and TO_CHAR(cssc.creationDate, 'yyyy-MM-dd') = TO_CHAR(:date, 'yyyy-MM-dd')
and (cssc.css.softwareVersion in (:softwareVersion)
or cssc.css.softwareVersion is null)";
Named Query, to fatch record where "softwareVersion" matched with the list only, no need to fatch null softwareVersion.
#NamedQuery(name = "getIPDetectionDetailsForPanIndiaAcceptNull",
query = "select cssc.css.sapId,
cssc.css.hostName,
cssc.cssGoldenConfiguration.category,
cssc.cssGoldenConfiguration.parameter,
cssc.cssGoldenConfiguration.vendor,
cssc.recommendedValue,
cssc.actualValue,
cssc.cssGoldenConfiguration.id,
cssc.cssGoldenConfiguration.information,
cssc.css.softwareVersion,
jioc.name,
cssc.cssGoldenConfiguration.impact,
cssc.cssGoldenConfiguration.command
from CssComplianceDetail cssc
join cssc.css c
left join c.cluster club
left join clus.jiocenter join
where cssc.cssGoldenConfiguration.impact in (:impactType)
and cssc.cssGoldenConfiguration.category in (:category)
and TO_CHAR(cssc.creationDate, 'yyyy-MM-dd') = TO_CHAR(:date, 'yyyy-MM-dd')
and cssc.css.softwareVersion in (:softwareVersion)";
Below is my Java code:
List softwareVersion = new ArrayList();
if(softwareVersion.contains("All")) {
query = getEntityManager().createNamedQuery("getIPDetectionCountForPanIndiaAcceptNull");
} else {
query = getEntityManager().createNamedQuery("getIPDetectionCountForPanIndia");
}
query.setParameter("softwareVersion", softwareVersion);
I have named queries which looks like the following:
#NamedQueries({
#NamedQuery(name = "table.getvalues", query = "select p from table p where p.a = :a and p.b = :b and p.c = :c order by id"),
#NamedQuery(name = "table.getvalueswhencisnull", query = "select p from table p where p.a = :a and p.b = :b and p.c is null order by id")
})
The only difference between 2 named queries is the the value of the c,c can be null and the syntax of the sql query differs only because of that.
Is there a way where I can club both the statements effectively?
use this :
select p from table p where p.a = :a and p.b = :b and (p.c is null or p.c=:c) order by id
Maybe this filter does a conditional selection.
...AND (p.c=:c OR (:c IS NULL and p.c IS NULL))...