使用JPA Criteria API时,直接使用ParameterExpression优于变量的优点是什么?例如。当我想的名字在一个字符串变量来搜索一个客户,我可以写类似使用参数表达式与JPA标准API中的变量API
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注入这样的参数有什么缺点吗?
在一般我不能JPA说话,但是我发现OpenJPA在内部将Criteria查询转换为JPQL,并且可以使用OpenJPA特定的功能打印(请参阅htt号码://openjpa.apache.org/builds/2.1.1/apache-openjpa/docs/ch13s03.html)。 第一个查询转换为“SELECT c FROM Customer c WHERE c.name ='test Customer'”。这意味着它不使用参数,所以如果这进一步转换为SQL,相应的准备语句将不使用参数。第二个版本转换为JPQL“SELECT c FROM Customer c WHERE c.name =:name”,所以我将使用参数。 – 2013-05-08 11:48:31
经过一些更多的测试后,我发现用JPQL编写相同的查询并使用名称“'或'x'='x”注入JPQL。使用标准API时,生成的OpenJPA日志JPQL看起来完全相同。然而,OpenJPA记录的实际SQL使用准备好的语句,在JPQL的情况下,参数值为“'或'x'='x”,而不是''。这意味着SQL注入在这里不起作用!不幸的是,我不知道这是多么可靠。这似乎是一个无证的功能。 – 2013-05-10 10:58:20
提示:我只是给了http://www.querydsl.com/一个尝试,它的语法更加简洁和可读。它似乎通过默认使用参数防止SQL注入。 – 2013-05-10 12:39:01