Klauzula JPQL IN: tablice Java (lub listy, zestawy…)?

108

Chciałbym załadować wszystkie obiekty, które mają przypisany tag tekstowy do dowolnej małej, ale dowolnej liczby wartości z naszej bazy danych. Logicznym sposobem rozwiązania tego problemu w SQL byłoby zbudowanie klauzuli „IN”. JPQL dopuszcza IN, ale wydaje się, że wymaga ode mnie bezpośredniego określenia każdego parametru na IN (jak w, "in (: in1,: in2,: in3)").

Czy istnieje sposób na określenie tablicy lub listy (lub innego kontenera), które powinny zostać rozwinięte do wartości klauzuli IN?

Bernd Haug
źródło

Odpowiedzi:

208

Nie jestem pewien dla JPA 1.0, ale możesz przejść Collectionw 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());

Przetestowano za pomocą EclipseLInk. W Hibernate 3.5.1 musisz otoczyć parametr nawiasami:

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

Ale to jest błąd, zapytanie JPQL w poprzednim przykładzie jest poprawnym JPQL. Zobacz HHH-5126 .

Pascal Thivent
źródło
5
czy istnieje maksymalna liczba nazw do użycia w „w klauzuli”?
Gondim
3
Wspomniany błąd w Hibernate wydaje się być naprawiony w wersji 3.6.1
Denis Kniazhev
1
@pringlesinn liczba wartości w klauzuli IN zależy od twojego DBMS
Tim Büthe
pracuje w JPA 1.0 (i jego brak obowiązkowego przestrzennego z nawiasu, ale dla czytelności zalecana)
Javier Larios
co jeśli chcesz => item.name w (like: names)
dzgeek
3

Limit wyroczni to 1000 parametrów. Problem został rozwiązany przez hibernację w wersji 4.1.7, chociaż przez podzielenie listy przekazanych parametrów na zestawy po 500, patrz JIRA HHH-1123

Ashish Thukral
źródło
1
Niestety nie udało się tego rozwiązać. Zgłoszenie zostało oznaczone jako rozwiązane, ale problem (jak pokazują komentarze) nie został naprawiony przez zespół Hibernate.
Druckles
@Druckles um gdzie? Nie widzę żadnych komentarzy starszych niż 2016. A to tylko dwa komentarze, które nie mówią praktycznie nic poza zwykłym internetowym „help plz !!! 11 !!!!”. Nie podałeś żadnego powodu, aby ufać zgłoszeniu błędu jako rozwiązanemu.
Searchengine 27
@earchchengine27 Powiedziałem, że raport nie został rozwiązany, mimo że został oznaczony jako rozwiązany. Rozwiązanie było, jak donosił Steve Ebersole: „Rozwiązanie jest takie, że będziemy po prostu ostrzegać użytkowników poprzez logowanie, gdy ten stan zostanie wykryty”. Komentarze Noela Trouta z 2012 roku wyjaśniają, dlaczego to nie wystarczy.
Druckles
Innymi słowy, ta odpowiedź jest błędna lub w najlepszym przypadku myląca.
Druckles