Параметр у подібному реченні JPQL


90

Я намагаюся написати запит JPQL з подібним реченням:

LIKE '%:code%'

Я хотів би мати код = 4 і знайти

455
554
646
...

Я не можу пройти :code = '%value%'

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

тому що в іншому місці мене :valueне потрібно загортати %символами. Будь-яка допомога?


2
@ Мануеле Піастра: Відповідь нижче - не те, що ви шукали?
wmorrison365

Відповіді:


169

Якщо ти зробиш

LIKE :code

а потім зробіть

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

Тоді значення залишається вільним від знака "%". Якщо вам потрібно використовувати його десь ще в тому самому запиті, просто використовуйте інше ім'я параметра, крім 'код'.


9
Для запису це не залишає вас відкритими для атак ін’єкцій JPQL, оскільки this.value автоматично для вас автоматично захищений.
Ласло ван ден Хук,

3
Це "%" + this.value + "%"те, що вдалося втекти.
Густаво,

2
Як зробити цей регістр нечутливим?
EM-Creations

55

Я не використовую іменовані параметри для всіх запитів. Наприклад, незвично використовувати названі параметри в JpaRepository .

Для обходу я використовую функцію JPQL CONCAT (емуляція коду починається з ):

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

Я знайшов цю техніку у чудових документах: http://openjpa.apache.org/builds/1.0.1/apache-openjpa-1.0.1/docs/manual/jpa_overview_query.html


2
Примітка: CONCAT (? 2, '%') додасть '%' до кінця параметра, використовуйте CONCAT ('%',? 2, '%'), щоб додати його до початку та кінця параметра.
Muizz Mahdy

7

Ви можете використовувати функцію JPA LOCATE .

LOCATE (searchString, kandidatString [, startIndex]) : Повертає перший індекс searchString у kandidatString. Позиції базуються на 1. Якщо рядок не знайдено, повертає 0.

FYI: Документація до мого найвідомішого звернення до Google змінила параметри.

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

1
для мене найкраще рішення - відсутність конкатенації, не введення SQL.
hgoebl

4

Я не знаю, запізнююсь я або виходжу за рамки, але, на мою думку, я міг би зробити це так:

String orgName = "anyParamValue";

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

q.setParameter("orgName", orgName);

2

Існує хороший метод like () в API критеріїв JPA. Спробуйте використати це, сподіваємось, це допоможе.

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. Використовуйте нижче запит JPQL.
select i from Instructor i where i.address LIKE CONCAT('%',:address ,'%')");
  1. Використовуйте нижче код критеріїв для того самого:
@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

Просто залиште "

LIKE %:code%

Голос проти: не працює, це змінює назву параметра на код%
kaiser

0

Використовувати JpaRepositoryабо CrudRepositoryяк інтерфейс сховища:

@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());
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.