Parámetro en cláusula similar JPQL


90

Estoy tratando de escribir una consulta JPQL con una cláusula similar:

LIKE '%:code%'

Me gustaría tener el código = 4 y encontrar

455
554
646
...

No puedo pasar :code = '%value%'

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

porque en otro lugar no necesito :valueenvolverme con los %caracteres. ¿Alguna ayuda?


2
@Manuele Piastra: ¿La respuesta a continuación no es lo que estaba buscando?
wmorrison365

Respuestas:


169

Si lo haces

LIKE :code

y luego haz

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

Entonces el valor permanece libre del signo '%'. Si necesita usarlo en otro lugar en la misma consulta, simplemente use otro nombre de parámetro que no sea 'código'.


9
Para el registro, esto no lo deja abierto a ataques de inyección de JPQL porque this.value se escapa automáticamente para usted.
László van den Hoek

3
Esto "%" + this.value + "%"es lo que se escapó.
Gustavo

2
¿Cómo hago para que esto no distinga entre mayúsculas y minúsculas?
EM-Creations

55

No utilizo parámetros con nombre para todas las consultas. Por ejemplo, es inusual utilizar parámetros con nombre en JpaRepository .

Para solucionar el problema, utilizo la función JPQL CONCAT (este código emula comenzar 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);
}

Encontré esta técnica en excelentes documentos: http://openjpa.apache.org/builds/1.0.1/apache-openjpa-1.0.1/docs/manual/jpa_overview_query.html


2
Nota: CONCAT (? 2, '%') agregará '%' al final del parámetro, use CONCAT ('%',? 2, '%') para agregarlo al principio y al final del parámetro.
Muizz Mahdy

7

Puede utilizar la función JPA LOCATE .

LOCATE (búsquedaString, CandidatoString [, StartIndex]) : Devuelve el primer índice de SearchString en CandidatoString. Las posiciones se basan en 1. Si no se encuentra la cadena, devuelve 0.

FYI: La documentación sobre mi éxito principal de Google tenía los parámetros invertidos.

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

1
para mí, la mejor solución: sin concatenación, sin inyección de SQL.
hgoebl

4

No sé si llego tarde o fuera de alcance pero en mi opinión podría hacerlo así:

String orgName = "anyParamValue";

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

q.setParameter("orgName", orgName);

2

Hay un buen método like () en la API de criterios JPA. Intenta usar eso, espero que te ayude.

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. Utilice la siguiente consulta JPQL.
select i from Instructor i where i.address LIKE CONCAT('%',:address ,'%')");
  1. Utilice el siguiente código de Criterios para lo mismo:
@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

Solo deja fuera el ''

LIKE %:code%

Votación en contra: no funciona, esto cambia el nombre del parámetro al código%
Kaiser

0

Utilice JpaRepositoryo CrudRepositorycomo interfaz de repositorio:

@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());
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.