0

I have a query where I expect 1000s of rows and I'm looking for values in two columns. Something like this

select
  *
from
  foo
WHERE
 (name, version)
in
  (('a','2.0.0'),('b','1.0.0'));

Then I learned that this is not possible in JPA and I converted the query to multiple OR and AND queries.

select
  *
from
  foo
WHERE
  name = 'a' and version = '2.0.0'
  or name = 'b' and version = '1.0.0'

I'm using a specification to build the query.

      var predicates =
          values.entrySet().stream()
              .map(
                  entry -> {
                    return cb.and(
                        cb.equal(root.get("name"),entry.getKey()),
                        cb.equal(root.get("version"), entry.getValue()));
                  })
              .toList();

      return cb.or(predicates.toArray(Predicate[]::new));

That works but it's very slow and other answer support my findings.

So now I'm trying to do something like this.

select
  *
from
(
    values
        ('a', '2.0.0'),
        ('b', '1.0.0')
) t(name, version)
left join
  foo
on t.name = foo.name and t.version = foo.version

Here is the official documentation.

https://www.postgresql.org/docs/current/queries-values.html

I'm having trouble translating this in to JPA or using a specification / criteria builder.

Any ideas? Or do I have to use a native query?

Thank you!

zemirco
  • 16,171
  • 8
  • 62
  • 96
  • In my hands your specification-built query works well. What version of PostgreSQL are you using and what indexes do you have? – jjanes Jan 02 '22 at 23:56
  • 1
    select * from foo WHERE `(`name = 'a' and version = '2.0.0' `)` or `(`name = 'b' and version = '1.0.0'`)` is missing parenthesis. – tinazmu Jan 03 '22 at 02:06
  • Or: `SELECT * FROM foo WHERE name & version IN ('a2.0.0', 'b1.0.0')` – June7 Jan 03 '22 at 04:52
  • The parenthesis aren't necessary. Check the operator precedence https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-PRECEDENCE. – zemirco Jan 04 '22 at 20:54

0 Answers0