Spring JPA @Query ile LIKE


96

CrudRepository'de, kullanıcı adları girdi parametresi GİBİ olan kullanıcıların listesini verebilecek bir yöntem oluşturmaya çalışıyorum (yalnızca ile başlayan değil, aynı zamanda onu da içeren). Yöntemi kullanmayı denedim "findUserByUsernameLike(@Param("username") String username)"ama Bahar dokümantasyonunda anlatıldığı gibi bu yöntem " where user.username like ?1" eşittir . Kullanıcı adı ... içeren tüm kullanıcıları almaya çalıştığımı söylediğim gibi benim için iyi değil.

Yönteme bir sorgu yazdım ama açılmıyor bile.

@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);
}

Biri bana bu konuda yardım edebilir mi?


4
containingİndekslerden yararlanmak için kullanmak isteyebilirsiniz , bkz. Docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/…

Yanıtlar:


175

Aşağıdaki yaklaşımı kullanmayı deneyin (benim için çalışıyor):

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

Not: JPQL'deki tablo adı büyük harfle başlamalıdır.


11
ya WHERE UPPER(u.username) LIKE CONCAT('%',UPPER(:username),'%')bir harf duyarsız arama yapmak
Brad Mace

Çözümünüzü kullanarak SQL Enjeksiyonu mümkün mü? (CONCAT nedeniyle soruyor)
ramden

@ramden tüm @Params sterilize edildi, bu yüzden hayır.
nurettin

Şunu yapabilirsiniz: username ve sonra .setParameter ("username", "% foo%");
Matthew Daumen

.setParameter ("kullanıcı adı", "% foo%") nasıl ayarlanır; @MatthewDaumen
xuezhongyu01

122

Yöntem adlarından sorgu oluşturmayı kullanarak , bazı anahtar kelimeleri açıkladıkları tablo 4'e bakın.

  1. Beğen kullanma: select ... like :username

     List<User> findByUsernameLike(String username);
    
  2. Başlarken: select ... like :username%

     List<User> findByUsernameStartingWith(String username);
    
  3. İle bitmek: select ... like %:username

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

     List<User> findByUsernameContaining(String username);
    

Aradığınız cevabın 4 numara olduğuna dikkat edin . @Query kullanmak zorunda değilsiniz


Bu gerçekten yararlı, ancak İçeren anahtar kelimesini kullanmak istersem, büyük / küçük harfe duyarlı olmasını da sağlayabilir miyim? Belgelerde StringMatcher hakkında söylenen bir şey var. Öyle görünüyor ki, ExampleMatcher ile ayrı bir işlev oluşturursam işe yarayacak, ancak bu büyük / küçük harf duyarlılığını eklemek için kendi işlevimi yazmamayı bir şekilde yöntem adında bildirebilir miyim?
V.Samma

11
Gerekirse durumu göz ardı edebileceğinizi de eklemek istedim, örneğin: List<User> findByUsernameContainingIgnoreCase(String username);
Robert

Yüzde sembolü ters çevrilmeli StartingWith: select ... like :username%ve EndingWith: select ... like %:username... her halükarda harika cevap ... kabul edilen cevap olmalıdır. Teşekkürler.
Alessandro

@Robert büyük harfli bir sütun verisine sahibim ve JPQL benzeri yöntem kullandım ve küçük harf değerini geçtim ve değerleri alabildim. IgnoreCase olmadan da uygunsuz durum verilerini alıyor. Bu tuhaf davranış neden oldu?
yeşil boynuz

@greenhorn Lütfen ayrı bir StackOverflow sorusu açın ve tabloya verileriniz ve ne için sorguladığınızla ilgili bazı örnekler ekleyin.
Robert

26

Başka bir yol: CONCATişlev yerine çift ​​boruyu kullanabiliriz :: soyad || '%'

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

Herhangi bir yere, önek, son ek veya her ikisini birden koyabilirsiniz

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

10

List<User> findByUsernameContainingIgnoreCase(String username);

vaka sorunlarını yok saymak için


Çözümünüzü kullanarak SQL Enjeksiyonu mümkün mü?
xuezhongyu01

@ xuezhongyu01 Spring Data JPA'nın türetilmiş sorgularında SQL enjeksiyonuna izin verdiğini mi düşünüyorsunuz? Elbette parametreler sterilize edilir.
Johannes Ebster


9

Durumunuz için doğrudan JPA yöntemlerini kullanabilirsiniz. Bu feryat gibidir:

İçeren: seçin ... gibi%: username%

List<User> findByUsernameContainingIgnoreCase(String username);

Burada, IgnoreCase , durumu görmezden gelerek öğeyi aramanıza yardımcı olacaktır.

İşte bazı ilgili yöntemler:

  1. Sevmek findByFirstnameLike

    … X.firstname nasıl olur? 1

  2. Başlangıç findByFirstnameStartingWith

    … Burada x.firstname? 1 gibi (parametre ekli% ile bağlı)

  3. İle bitmek findByFirstnameEndingWith

    … Burada x.firstname gibi? 1 (parametre başına eklenen% ile bağlı)

  4. Kapsamak findByFirstnameContaining

    … Burada x.firstname? 1 gibi (parametre bağlama% olarak sarılmış)

Daha fazla bilgi, bu bağlantıyı görüntüleyin ve bu bağlantıyı görüntüleyin

Umarım bu size yardımcı olur :)


1
Teşekkürler! JPA kurallarını kullanmak doğru yol gibi geliyor.
FigletNewton

3

Bu yöntem benim için işe yarar (Spring Boot sürüm 2.0.1. SÜRÜMÜ kullanarak):

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

Açıklama:? 1,? 2,? 3 vb. Birinci, ikinci, üçüncü parametreler vb. Yer tutuculardır. Bu durumda parametrenin, standart bir SQL sorgusuymuş gibi ancak tek tırnak.


1
Sayılar yerine adlandırılmış parametreleri tercih etmelisiniz:@Query("SELECT u.username FROM User u WHERE u.username LIKE %:username%")
Ralph

@Ralph, bunu senin yolunu kullanarak başarmaya çalışıyorum, ama 2 nesne içeren bir liste almam gerekirken her zaman 0 nesneli bir liste alıyorum, bununla ilgili bir şey önerir misin lütfen? bu stackoverflow.com/questions/65085720/… ile
Subha Bhowmik

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

Teşekkürler, deplouing problemi jpql'nin büyük / küçük harfe duyarlı olmasıydı, şimdi dağıtılıyor ama 'LIKE' istediğim gibi çalışmıyor. Yalnızca girdi parametresine tamamen eşit olan kayıtları bulur (onu içermeyen).
Viktoriia

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

Bu kodu denedim ve çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.