If I pass an empty list into a JPA query, I get an error. For example:
List municipalities = myDao.findAll(); // returns empty list
em.c
I struggled with this issue, too. I found out that the Hibernate community has RESOLVED the issue in Hibernate version 5.4.10, here is the ticket: https://hibernate.atlassian.net/browse/HHH-8091
You can check your Hibernate version System.out.println(org.hibernate.Version.getVersionString());
And you can UPDATE the version of Hibernate to the latest, here is a useful link: https://bintray.com/hibernate/artifacts/hibernate-orm#
Since you're querying DB sequence IDs that typically start at 1, you can add 0 to the list
if (excludeIds.isEmpty()) {
excludeIds.add(new Long("0"));
}
List<SomeEntity> retval = someEntityRepo.findByIdNotIn(excludeIds);
Maybe -1 works too. Small work around for the use of jpa repos.
Solution:
if (municipalities==null || municipalities.isEmpty())
.setParameter("municipalities", "''")
else
.setParameter("municipalities", municipalities)
Assuming the SQL query to be like
(COALESCE(:placeHolderName,NULL) IS NULL OR Column_Name in (:placeHolderName))
Now, If the List is of type String then you can pass as
query.setParameterList("placeHolderName",
!CollectionUtils.isEmpty(list)? list : new ArrayList<String>(Arrays.asList("")).
And If the List is containing the Integer values then the syntax is like below:
If(!CollectionUtils.isEmpty(list)){
query.setParameterList("placeHolderName",list)
}else{
query.setParameter("placeHolderName",null, Hibernate.INTEGER)
}
If you are using spring/hibernate annotations then one of the easiest ways of working around this is having two parameters. First lets define our JPA annotation:
+ "AND (p.myVarin :state OR :nullCheckMyVar is null) "
Then pass those parameters in as normal:
@Param("myVarin") List<Integers> myVarin,
@Param("nullCheckMyVar") Integer nullCheckMyVar,
Finally in what ever service call you can do the following:
Integer nullCheckInteger = null;
if (myVarIn != null && !myVarIn.isEmpty()) {
// we can use any integer
nullCheckInteger = 1;
}
repo.callService(myVarIn, nullCheckInteger);
And then pass those two parms into the call.
What does this do? If myVarIn is not null and filled then we can specify "all" as 1 != null. Otherwise we pass in our list and null is null and therefore ignored. This either selects "all" when empty or something when not empty.
According to the section 4.6.8 In Expressions from the JPA 1.0 specification:
There must be at least one element in the comma separated list that defines the set of values for the
IN
expression.
In other words, regardless of Hibernate's ability to parse the query and to pass an IN()
, regardless of the support of this syntax by particular databases (PosgreSQL doesn't according to the Jira issue), you should use a dynamic query here if you want your code to be portable (and I usually prefer to use the Criteria API for dynamic queries).