Используя выражение ParameterExpression и переменную в API-интерфейсе JPA

При использовании API-критериев JPA, в чем преимущество использования ParameterExpression над переменной напрямую? Например. когда я хочу искать клиента по имени в переменной String, я мог бы написать что-то вроде

private List<Customer> findCustomer(String name) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Customer> criteriaQuery = cb.createQuery(Customer.class);
    Root<Customer> customer = criteriaQuery.from(Customer.class);
    criteriaQuery.select(customer).where(cb.equal(customer.get("name"), name));
    return em.createQuery(criteriaQuery).getResultList();
}

С параметрами это будет:

private List<Customer> findCustomerWithParam(String name) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Customer> criteriaQuery = cb.createQuery(Customer.class);
    Root<Customer> customer = criteriaQuery.from(Customer.class);
    ParameterExpression<String> nameParameter = cb.parameter(String.class, "name");
    criteriaQuery.select(customer).where(cb.equal(customer.get("name"), nameParameter));
    return em.createQuery(criteriaQuery).setParameter("name", name).getResultList();
}

Для краткости я предпочел бы первый способ, особенно когда запрос увеличивается с дополнительными параметрами. Есть ли недостатки в использовании таких параметров, как SQL-инъекция?

Ответ 1

При использовании параметра, вероятного (в зависимости от реализации JPA, используемого хранилища данных и драйвера JDBC) SQL будет оптимизирован для параметра JDBC, поэтому, если вы выполняете одно и то же с другим значением параметра, он использует тот же самый JDBC.

SQL-инъекция всегда относится к разработчику относительно того, проверяют ли они некоторый пользовательский ввод, который используется как параметр.

Ответ 2

вы можете использовать ParameterExpression следующим образом: предположим, что у вас есть входной фильтр, примером может быть:

  • в вашем запросе вы должны проверить значение фискального кода.

пусть начнется: сначала создайте критерииQuery и критерииBuilder и root

        CriteriaBuilder cb = _em.getCriteriaBuilder();
        CriteriaQuery<Tuple> cq = cb.createTupleQuery();
        Root<RootEntity> soggettoRoot = cq.from(RootEntity.class);

1) инициализировать предикатList (использовать для предложения where) и paramList (использовать для param)

Map<ParameterExpression,String> paramList = new HashMap();
List<Predicate> predicateList = new ArrayList<>();

2) проверьте, является ли вход нулевым и создайте предикатList и param

if( input.getFilterCF() != null){
            //create ParameterExpression
            ParameterExpression<String> cf = cb.parameter(String.class);


           //if like clause
            predicateList.add(cb.like(root.<String>get("cf"), cf));
            paramList.put(cf , input.getFilterCF() + "%");

           //if equals clause
           //predicateList.add(cb.equal(root.get("cf"), cf));   
           //paramList.put(cf,input.getFilterCF()());
        }

3) создайте предложение where

 cq.where(cb.and(predicateList.toArray(new   Predicate[predicateList.size()])));
TypedQuery<Tuple> q = _em.createQuery(cq);

4) установить значение параметра

        for(Map.Entry<ParameterExpression,String> entry : paramList.entrySet())
        {
            q.setParameter(entry.getKey(), entry.getValue());
        }