Parametr w podobnej klauzuli JPQL

90

Próbuję napisać zapytanie JPQL z klauzulą ​​like:

LIKE '%:code%'

Chciałbym mieć kod = 4 i znaleźć

455
554
646
...

Nie mogę przejść :code = '%value%'

namedQuery.setParameter("%" + this.value + "%");

ponieważ w innym miejscu nie muszę :valuezawijać %znaków. Jakaś pomoc?

Manuel Drieschmanns
źródło
2
@Manuele Piastra: Czy odpowiedź poniżej nie jest tym, czego szukałeś?
wmorrison365

Odpowiedzi:

169

Jeśli zrobisz

LIKE :code

a potem zrób

namedQuery.setParameter("code", "%" + this.value + "%");

Wtedy wartość pozostaje wolna od znaku „%”. Jeśli chcesz użyć go w innym miejscu w tym samym zapytaniu, po prostu użyj innej nazwy parametru niż „kod”.

kapitan statku
źródło
9
Dla przypomnienia, nie pozostawia to otwartego na ataki typu JPQL, ponieważ this.value jest automatycznie poprawne.
László van den Hoek
3
To "%" + this.value + "%"jest to, czego się uniknęło.
Gustavo
2
Jak wyłączyć rozróżnianie wielkości liter?
EM-Creations
55

Nie używam nazwanych parametrów dla wszystkich zapytań. Na przykład nietypowe jest używanie nazwanych parametrów w JpaRepository .

Aby obejść ten problem, używam funkcji JPQL CONCAT (ten kod zaczyna emulować ):

@Repository
public interface BranchRepository extends JpaRepository<Branch, String> {
    private static final String QUERY = "select b from Branch b"
       + " left join b.filial f"
       + " where f.id = ?1 and b.id like CONCAT(?2, '%')";
    @Query(QUERY)
    List<Branch> findByFilialAndBranchLike(String filialId, String branchCode);
}

Znalazłem tę technikę w znakomitych dokumentach: http://openjpa.apache.org/builds/1.0.1/apache-openjpa-1.0.1/docs/manual/jpa_overview_query.html

gavenkoa
źródło
2
Uwaga: CONCAT (? 2, „%”) doda „%” na końcu parametru, użyj CONCAT („%”,? 2, „%”), aby dodać go na początku i na końcu parametru.
Muizz Mahdy
7

Możesz użyć funkcji JPA LOCATE .

LOCATE (searchString, patientString [, startIndex]) : Zwraca pierwszy indeks elementu searchString w łańcuchu kandydatów. Pozycje są oparte na 1. Jeśli ciąg nie zostanie znaleziony, zwraca 0.

FYI: Dokumentacja mojego najpopularniejszego hitu Google miała odwrócone parametry.

SELECT 
  e
FROM 
  entity e
WHERE
  (0 < LOCATE(:searchStr, e.property))
David Carlson
źródło
1
dla mnie najlepsze rozwiązanie - bez konkatenacji, bez iniekcji SQL.
hgoebl
4

Nie wiem, czy jestem spóźniony czy poza zakresem ale moim zdaniem mógłbym to zrobić tak:

String orgName = "anyParamValue";

Query q = em.createQuery("Select O from Organization O where O.orgName LIKE '%:orgName%'");

q.setParameter("orgName", orgName);
Ishimwe Aubain Consolateur
źródło
2

W API kryteriów JPA jest ładna metoda like (). Spróbuj tego użyć, miej nadzieję, że to pomoże.

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery criteriaQuery = cb.createQuery(Employees.class);
Root<Employees> rootOfQuery = criteriaQuery.from(Employees.class);
criteriaQuery.select(rootOfQuery).where(cb.like(rootOfQuery.get("firstName"), "H%"));
Haroon
źródło
1
  1. Użyj poniższego zapytania JPQL.
select i from Instructor i where i.address LIKE CONCAT('%',:address ,'%')");
  1. Użyj poniższego kodu kryteriów dla tego samego:
@Test
public void findAllHavingAddressLike() {
    CriteriaBuilder cb = criteriaUtils.criteriaBuilder();
    CriteriaQuery<Instructor> cq = cb.createQuery(Instructor.class);
    Root<Instructor> root = cq.from(Instructor.class);
    printResultList(cq.select(root).where(
        cb.like(root.get(Instructor_.address), "%#1074%")));
}
Vaneet Kataria
źródło
0

Po prostu pomiń ''

LIKE %:code%
Sehtim
źródło
Głos przeciw: nie działa, zmienia to nazwę parametru na kod%
kaiser
0

Użyj JpaRepositorylub CrudRepositoryjako interfejsu repozytorium:

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer> {

    @Query("SELECT t from Customer t where LOWER(t.name) LIKE %:name%")
    public List<Customer> findByName(@Param("name") String name);

}


@Service(value="customerService")
public class CustomerServiceImpl implements CustomerService {

    private CustomerRepository customerRepository;
    
    //...

    @Override
    public List<Customer> pattern(String text) throws Exception {
        return customerRepository.findByName(text.toLowerCase());
    }
}
KarishmaP
źródło