I have a table with a name column that is important to me.
insert into tab (name) values ('a');
insert into tab (name) values ('b');
insert into tab (name) values ('c');
insert into tab (name) values ('d');
From my Spring Data Repository backed by Hibernate 5, I want to pass a List of names and return which names are not present in the table from what was passed in. So for list ('a', 'b', 'c', 'baz') it should return a single row with value baz.
The following query would work for this scenario if written by hand.
WITH list(name) AS (VALUES ('a'), ('b'), ('c'), ('baz'))
SELECT name
FROM list
EXCEPT
SELECT name
FROM tab
WHERE name IN (SELECT name FROM list)
So I add the following method to my JpaRepository.
@Query(value = "WITH list(name) "
+ " AS (VALUES :names) "
+ "SELECT name "
+ "FROM list "
+ " EXCEPT "
+ "SELECT name "
+ "FROM tab "
+ "WHERE name IN (SELECT name FROM list)", nativeQuery = true)
List<String> findNamessMissingFromGivenList(Collection<String> names);
However, the way that Spring Data passes in :name Collection is by placing ('a', 'b', 'c', 'baz') instead of ('a'), ('b'), ('c'), ('baz'). So Collections work great for IN clauses but not this scenario. Essentially I need to pass in the list and make them into a pseudo-table like what VALUES does.
I would prefer not to build up any queries by hand and to avoid SQL injection. Is there a way to modify this query to accept a Collection from JPA?