Parametro nella clausola like JPQL


90

Sto cercando di scrivere una query JPQL con una clausola like:

LIKE '%:code%'

Vorrei avere code = 4 e trovare

455
554
646
...

Non posso passare :code = '%value%'

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

perché in un altro posto non ho bisogno di :valueavvolgere i %caratteri. Qualsiasi aiuto?


2
@Manuele Piastra: la risposta qui sotto non è quella che stavi cercando?
wmorrison365

Risposte:


169

Se fate

LIKE :code

e poi fallo

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

Quindi il valore rimane libero dal segno "%". Se è necessario utilizzarlo da qualche altra parte nella stessa query, utilizzare semplicemente un altro nome di parametro diverso da "codice".


9
Per la cronaca, questo non ti lascia aperto agli attacchi di iniezione JPQL perché this.value viene automaticamente evitato correttamente per te.
László van den Hoek

3
Questo "%" + this.value + "%"è ciò che è sfuggito.
Gustavo

2
Come faccio a rendere questo case-insensitive?
EM-Creations

55

Non uso parametri denominati per tutte le query. Ad esempio, è insolito utilizzare parametri denominati in JpaRepository .

Per aggirare il problema utilizzo la funzione CONCAT di JPQL (questo codice emula inizia con ):

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

Ho trovato questa tecnica in ottimi documenti: http://openjpa.apache.org/builds/1.0.1/apache-openjpa-1.0.1/docs/manual/jpa_overview_query.html


2
Nota: CONCAT (? 2, '%') aggiungerà '%' alla fine del parametro, utilizzare CONCAT ('%',? 2, '%') per aggiungerlo all'inizio e alla fine del parametro.
Muizz Mahdy,

7

Potresti usare la funzione JPA LOCATE .

LOCATE (searchString, candidateString [, startIndex]) : restituisce il primo indice di searchString in candidateString. Le posizioni sono in base 1. Se la stringa non viene trovata, restituisce 0.

FYI: La documentazione sul mio principale hit di Google aveva i parametri invertiti.

SELECT 
  e
FROM 
  entity e
WHERE
  (0 < LOCATE(:searchStr, e.property))

1
per me la soluzione migliore: nessuna concatenazione, nessuna iniezione SQL.
hgoebl

4

Non so se sono in ritardo o fuori campo ma secondo me potrei farlo in questo modo:

String orgName = "anyParamValue";

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

q.setParameter("orgName", orgName);

2

C'è un bel metodo like () nell'API dei criteri JPA. Prova a usarlo, spero che ti aiuti.

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%"));

1
  1. Usa sotto la query JPQL.
select i from Instructor i where i.address LIKE CONCAT('%',:address ,'%')");
  1. Usa il codice dei criteri di seguito per lo stesso:
@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%")));
}

0

Basta lasciare fuori il ''

LIKE %:code%

Voto negativo: non funziona, cambia il nome del parametro in codice%
kaiser

0

Usa JpaRepositoryo CrudRepositorycome interfaccia del repository:

@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());
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.