133

I would like to load all objects that have a textual tag set to any of a small but arbitrary number of values from our database. The logical way to go about this in SQL would be to build an "IN" clause. JPQL allows for IN, but it seems to require me to specify every single parameter to IN directly (as in, "in (:in1, :in2, :in3)").

Is there some way to specify an array, or a list (or some other container) that should be unrolled to the values of an IN clause?

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
Bernd Haug
  • 2,157
  • 3
  • 17
  • 21

3 Answers3

238

I'm not sure for JPA 1.0 but you can pass a Collection in JPA 2.0:

String qlString = "select item from Item item where item.name IN :names"; 
Query q = em.createQuery(qlString, Item.class);

List<String> names = Arrays.asList("foo", "bar");

q.setParameter("names", names);
List<Item> actual = q.getResultList();

assertNotNull(actual);
assertEquals(2, actual.size());

Tested with EclipseLInk. With Hibernate 3.5.1, you'll need to surround the parameter with parenthesis:

String qlString = "select item from Item item where item.name IN (:names)";

But this is a bug, the JPQL query in the previous sample is valid JPQL. See HHH-5126.

Arend v. Reinersdorff
  • 4,110
  • 2
  • 36
  • 40
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
3

The oracle limit is 1000 parameters. The issue has been resolved by hibernate in version 4.1.7 although by splitting the passed parameter list in sets of 500 see JIRA HHH-1123

Ashish Thukral
  • 1,445
  • 1
  • 16
  • 26
  • 2
    Unfortunately this was not resolved. The ticket was marked as resolved, but the problem (as shown by the comments) was not fixed by the Hibernate team. – Druckles Jul 06 '18 at 15:17
  • @Druckles um where? I don't see any comments older than 2016. And those were only two comments that say practically nothing other than the usual internet 'help plz!!!11!!!!'. You have given no reason to trust the bug report as resolved. – searchengine27 Jan 07 '20 at 21:19
  • @searchengine27 I said the report was *not* resolved, despite it being marked as resolved. The resolution was, as reported by Steve Ebersole: "The resolution to this is that we are simply going to warn users via logging when this condition is detected." The comments by Noel Trout back in 2012 expand on why this is not sufficient. – Druckles Jan 07 '20 at 23:18
  • In other words, this answer is wrong or, at best, misleading. – Druckles Jan 07 '20 at 23:19
3

I had a problem with this kind of sql, I was giving empty list in IN clause(always check the list if it is not empty). Maybe my practice will help somebody.

Vahan Yeghyan
  • 487
  • 5
  • 7