Wiosna JPA @Query z LIKE


95

Próbuję stworzyć metodę w CrudRepository, która będzie w stanie podać mi listę użytkowników, których nazwy użytkowników są TAKIE JAK parametr wejściowy (nie tylko zaczynają się, ale również zawierają). Próbowałem użyć metody, "findUserByUsernameLike(@Param("username") String username)"ale jak jest powiedziane w dokumentacji Spring, ta metoda jest równa " where user.username like ?1". Nie jest to dla mnie dobre, ponieważ już powiedziałem, że próbuję zdobyć wszystkich użytkowników, których nazwa użytkownika zawiera ...

Napisałem zapytanie do metody, ale ona nawet się nie wdraża.

@Repository
public interface UserRepository extends CrudRepository<User, Long> {

@Query("select u from user u where u.username like '%username%'")
List<User> findUserByUsernameLike(@Param("username") String username);
}

Czy ktoś może mi w tym pomóc?


4
Możesz chcieć użyć containing, aby skorzystać z indeksów, patrz docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/…

Odpowiedzi:


173

Spróbuj zastosować następujące podejście (u mnie działa):

@Query("SELECT u.username FROM User u WHERE u.username LIKE CONCAT('%',:username,'%')")
List<String> findUsersWithPartOfName(@Param("username") String username);

Uwaga: nazwa tabeli w JPQL musi zaczynać się wielką literą.


11
lub WHERE UPPER(u.username) LIKE CONCAT('%',UPPER(:username),'%')do wyszukiwania bez rozróżniania wielkości liter
Brad Mace

Możliwe SQL-Injection przy użyciu Twojego rozwiązania? (pytając z powodu CONCAT)
ramden

@ramden wszystkie @Paramsą odkażone, więc nie.
nurettin

Możesz po prostu zrobić: nazwa użytkownika, a następnie .setParameter ("nazwa użytkownika", "% foo%");
Matthew Daumen

jak ustawić .setParameter ("nazwa użytkownika", "% foo%"); @MatthewDaumen
xuezhongyu01

122

Używając tworzenia zapytań na podstawie nazw metod , sprawdź tabelę 4, w której objaśniono niektóre słowa kluczowe.

  1. Korzystanie z Like: select ... like :username

     List<User> findByUsernameLike(String username);
    
  2. Począwszy od: select ... like :username%

     List<User> findByUsernameStartingWith(String username);
    
  3. Kończące się: select ... like %:username

     List<User> findByUsernameEndingWith(String username);
    
  4. Zawierający: select ... like %:username%

     List<User> findByUsernameContaining(String username);
    

Zwróć uwagę, że odpowiedź, której szukasz, to numer 4 . Nie musisz używać @Query


To bardzo pomocne, ale jeśli chcę użyć słowa kluczowego Containing, czy mogę również ustawić bez rozróżniania wielkości liter? W dokumentacji jest coś powiedziane o StringMatcherze. Wygląda na to, że gdybym utworzył oddzielną funkcję za pomocą ExampleMatchera, zadziałałaby, ale czy mogę w jakiś sposób zadeklarować ją w nazwie metody, aby nie pisać własnej funkcji tylko po to, aby dodać tę niewrażliwość na wielkość liter?
V. Samma

11
Chciałem tylko dodać, że w razie potrzeby możesz również zignorować przypadek, na przykład: List<User> findByUsernameContainingIgnoreCase(String username);
Robert

Symbol procentu powinien być odwrócony StartingWith: select ... like :username%i EndingWith: select ... like %:username... w każdym razie świetna odpowiedź ... powinna być akceptowana. Dzięki.
Alessandro

@Robert Mam dane w kolumnie z dużymi literami i użyłem metody podobnej do JPQL i przekazałem wartość małych liter i mogłem uzyskać wartości. bez IgnoreCase również pobiera nieprawidłowe dane przypadków. Dlaczego zdarzyło się to dziwne zachowanie?
nowicjusz

@greenhorn Otwórz osobne pytanie StackOverflow i dodaj przykład swoich danych w tabeli oraz to, o co prosisz.
Robert

25

Inny sposób: zamiast CONCATfunkcji możemy użyć podwójnej kreski:: lastname || „%”

@Query("select c from Customer c where c.lastName LIKE :lastname||'%'")
List<Customer> findCustomByLastName( @Param("lastname") String lastName);

Możesz wstawić dowolne miejsce, prefiks, sufiks lub oba

:lastname ||'%'  
'%' || :lastname  
'%' || :lastname || '%'  

10

List<User> findByUsernameContainingIgnoreCase(String username);

aby zignorować problemy ze sprawami


Możliwe SQL-Injection przy użyciu Twojego rozwiązania?
xuezhongyu01

9

W twoim przypadku możesz bezpośrednio użyć metod JPA. To jest jak poniżej:

Zawiera: wybierz ... jak%: nazwa użytkownika%

List<User> findByUsernameContainingIgnoreCase(String username);

tutaj IgnoreCase pomoże ci wyszukać element z ignorowaniem przypadku.

Oto kilka powiązanych metod:

  1. Lubić findByFirstnameLike

    … Gdzie x.firstname jak? 1

  2. Zaczynając od findByFirstnameStartingWith

    … Gdzie x.firstname jak? 1 (parametr powiązany z dołączonym%)

  3. EndingWith findByFirstnameEndingWith

    … Gdzie x.firstname jak? 1 (parametr powiązany z przedrostkiem%)

  4. Zawierający findByFirstnameContaining

    … Gdzie x.firstname jak? 1 (parametr powiązany z%)

Więcej informacji, zobacz ten link i ten link

Mam nadzieję, że to ci pomoże :)


1
Dzięki! Używanie konwencji JPA wydaje się być właściwym sposobem.
FigletNewton


3

Ten sposób działa dla mnie (używając Spring Boot w wersji 2.0.1. RELEASE):

@Query("SELECT u.username FROM User u WHERE u.username LIKE %?1%")
List<String> findUsersWithPartOfName(@Param("username") String username);

Wyjaśnienie:? 1,? 2,? 3 itd. To symbole zastępcze pierwszego, drugiego, trzeciego parametru itd. W tym przypadku wystarczy, aby parametr był otoczony przez%, tak jakby to było standardowe zapytanie SQL, ale bez pojedyncze cytaty.


1
powinieneś preferować wymienione parametry zamiast liczb:@Query("SELECT u.username FROM User u WHERE u.username LIKE %:username%")
Ralph

0
@Query("select u from user u where u.username LIKE :username")
List<User> findUserByUsernameLike(@Param("username") String username);

Dzięki, problem z deplouowaniem polegał na tym, że jpql rozróżnia wielkość liter, teraz jest wdrażany, ale „LIKE” nie działa tak, jak chcę. Znajduje tylko rekordy, które są całkowicie równe parametrowi wejściowemu (nie zawierają go).
Viktoriia

-1
@Query("select b.equipSealRegisterId from EquipSealRegister b where b.sealName like %?1% and b.deleteFlag = '0'" )
    List<String>findBySeal(String sealname);

Wypróbowałem ten kod i działa.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.