java 在 JPA Criteria API 中使用 ParameterExpression 与变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16438365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 22:56:53  来源:igfitidea点击:

using a ParameterExpression versus a variable in JPA Criteria API

javaapijpacriteria

提问by Henno Vermeulen

When using the JPA Criteria API, what is the advantage of using a ParameterExpression over a variable directly? E.g. when I wish to search for a customer by name in a String variable, I could write something like

使用 JPA Criteria API 时,直接使用 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();
}

With parameters this becomes:

使用参数,这将变为:

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

For conciseness I would prefer the first way, especially when the query gets longer with optional parameters. Are there any disadvantages of using parameters like this, like SQL injection?

为简洁起见,我更喜欢第一种方式,尤其是当查询变得更长并且带有可选参数时。使用像 SQL 注入这样的参数有什么缺点吗?

回答by Taioli Francesco

you can use ParameterExpression like this: assume that you have some input filter, an example could be this:

你可以像这样使用 ParameterExpression:假设你有一些输入过滤器,一个例子可能是这样的:

  • in your query you have to check the value of a fiscal Code.
  • 在您的查询中,您必须检查财务代码的值。

let's start: first of all create criteriaQuery and criteriaBuilder and root

让我们开始: 首先创建criteriaQuery 和criteriaBuilder 和root

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

1)inizialize a predicateList(use for where clause) and a paramList(use for param)

1)初始化一个 predicateList(用于 where 子句)和一个 paramList(用于 param)

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

2)check if the input is null and create predicateList and param

2) 检查输入是否为空并创建 predicateList 和 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) create the where clause

3) 创建 where 子句

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

4) set param value

4) 设置参数值

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

回答by DataNucleus

When using a parameter, likely (dependent on JPA implementation, datastore in use, and JDBC driver) the SQL will be optimised to a JDBC parameter so if you execute the same thing with a different value of the parameter it uses the same JDBC statement.

使用参数时,很可能(取决于 JPA 实现、使用中的数据存储和 JDBC 驱动程序)SQL 将优化为 JDBC 参数,因此如果您使用不同的参数值执行相同的操作,它将使用相同的 JDBC 语句。

SQL injection is always down to the developer as to whether they validate some user input that is being used as a parameter.

SQL 注入始终取决于开发人员是否验证用作参数的某些用户输入。