Используя выражение 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());
}