Paramètre dans la clause similaire JPQL

90

J'essaye d'écrire une requête JPQL avec une clause similaire:

LIKE '%:code%'

Je voudrais avoir code = 4 et trouver

455
554
646
...

Je ne peux pas passer :code = '%value%'

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

parce que dans un autre endroit, je n'ai :valuepas besoin d' être enveloppé par les %caractères. De l'aide?

Manuel Drieschmanns
la source
2
@Manuele Piastra: La réponse ci-dessous n'est-elle pas celle que vous cherchiez?
wmorrison365

Réponses:

169

Si tu fais

LIKE :code

puis fais

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

La valeur reste alors libre du signe «%». Si vous avez besoin de l'utiliser ailleurs dans la même requête, utilisez simplement un autre nom de paramètre autre que «code».

capitaine
la source
9
Pour mémoire, cela ne vous laisse pas ouvert aux attaques par injection JPQL car this.value est automatiquement correctement échappé pour vous.
László van den Hoek
3
C'est "%" + this.value + "%"ce qui s'est échappé.
Gustavo le
2
Comment rendre cela insensible à la casse?
EM-Creations
55

Je n'utilise pas de paramètres nommés pour toutes les requêtes. Par exemple, il est inhabituel d'utiliser des paramètres nommés dans JpaRepository .

Pour contourner le problème , j'utilise la fonction JPQL CONCAT (cette émulation de code commence par ):

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

J'ai trouvé cette technique dans d'excellents documents: http://openjpa.apache.org/builds/1.0.1/apache-openjpa-1.0.1/docs/manual/jpa_overview_query.html

gavenkoa
la source
2
Remarque: CONCAT (? 2, '%') ajoutera '%' à la fin du paramètre, utilisez CONCAT ('%',? 2, '%') pour l'ajouter au début et à la fin du paramètre.
Muizz Mahdy
7

Vous pouvez utiliser la fonction JPA LOCATE .

LOCATE (searchString, candidateString [, startIndex]) : renvoie le premier index de searchString dans candidateString. Les positions sont basées sur 1. Si la chaîne n'est pas trouvée, renvoie 0.

FYI: La documentation sur mon top google hit avait les paramètres inversés.

SELECT 
  e
FROM 
  entity e
WHERE
  (0 < LOCATE(:searchStr, e.property))
David Carlson
la source
1
pour moi la meilleure solution - pas de concaténation, pas d'injection SQL.
hgoebl
4

Je ne sais pas si je suis en retard ou hors de portée mais à mon avis, je pourrais le faire comme:

String orgName = "anyParamValue";

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

q.setParameter("orgName", orgName);
Ishimwe Aubain Consolateur
la source
2

Il existe une belle méthode like () dans l'API de critères JPA. Essayez de l'utiliser, j'espère que cela vous aidera.

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
la source
1
  1. Utilisez ci-dessous la requête JPQL.
select i from Instructor i where i.address LIKE CONCAT('%',:address ,'%')");
  1. Utilisez ci-dessous le code des critères pour le même:
@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
la source
0

Laissez de côté le ''

LIKE %:code%
Sehtim
la source
Downvote: ne fonctionne pas, cela change le nom du paramètre en code%
kaiser
0

Utilisez JpaRepositoryou CrudRepositorycomme interface de référentiel:

@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
la source