Tin*_*iny 9 hibernate jpa criteria prepared-statement eclipselink
Hibernate提供程序不会为非字符串类型参数生成预准备语句,除非它们entityManager.createQuery(criteriaQuery).setParameter(Parameter p, T t);默认设置为由EclipseLink完成.
设置此类参数的方法是什么,如果它们是在运行时动态提供的.例如,
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Long>criteriaQuery=criteriaBuilder.createQuery(Long.class);
Metamodel metamodel=entityManager.getMetamodel();
EntityType<Product> entityType = metamodel.entity(Product.class);
Root<Product> root = criteriaQuery.from(entityType);
criteriaQuery.select(criteriaBuilder.count(root));
List<Predicate>predicates=new ArrayList<Predicate>();
for (Map.Entry<String, String> entry : filters.entrySet()) {
    if (entry.getKey().equalsIgnoreCase("prodId")) {
        predicates.add(criteriaBuilder.equal(root.get(Product_.prodId), Long.parseLong(entry.getValue().trim())));
    } else if (entry.getKey().equalsIgnoreCase("prodName")) {
        predicates.add(criteriaBuilder.like(root.get(Product_.prodName), "%" + entry.getValue().trim() + "%"));
    } else if (entry.getKey().equalsIgnoreCase("marketPrice")) {
        predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(Product_.marketPrice), new BigDecimal(entry.getValue().trim())));
    } else if (entry.getKey().equalsIgnoreCase("salePrice")) {
        predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(Product_.salePrice), new BigDecimal(entry.getValue().trim())));
    } else if (entry.getKey().equalsIgnoreCase("quantity")) {
        predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(Product_.quantity), Integer.valueOf(entry.getValue().trim())));
    }
}
if (!predicates.isEmpty()) {
    criteriaQuery.where(predicates.toArray(new Predicate[0]));
}
Long count = entityManager.createQuery(criteriaQuery).getSingleResult();
在这种情况下,参数to prodName是String类型参数.因此,它自动绑定到位置参数?.其余(非字符串类型)则不是.他们都被他们的价值所取代.
createQuery()例如,它们需要设置为
ParameterExpression<BigDecimal> exp=criteriaBuilder.parameter(BigDecimal.class);
entityManager.createQuery(criteriaQuery).setParameter(exp, new BigDecimal(1000));
如何设置这样的动态参数,以便生成准备好的查询?
这在EclipseLink中确实不是必需的,它们会自动映射到位置参数.
可以用Hibernate提供程序完成吗?
我正在使用Hibernate 4.2.7 final提供的JPA 2.0.
如果设置了所有参数,则上述条件查询生成的语句如下所示.
SELECT count(product0_.prod_id) AS col_0_0_ 
FROM   projectdb.product product0_ 
WHERE  product0_.market_price >= 1000 
       AND ( product0_.prod_name LIKE ? ) 
       AND product0_.prod_id = 1 
       AND product0_.quantity >= 1 
       AND product0_.sale_price >= 1000 
我刚刚在EclipseLink(2.3.2)下运行上面的条件查询,导致生成以下SQL语句.
SELECT count(prod_id) 
FROM   projectdb.product 
WHERE  ( ( ( ( ( market_price >= ? ) 
           AND prod_name LIKE ? ) 
         AND ( prod_id = ? ) ) 
       AND ( quantity >= ? ) ) 
     AND ( sale_price >= ? ) ) 
bind => [1000, %product1%, 1, 1, 1000]
即参数化查询.
如下所示是不可能的.
//...
TypedQuery<Long> typedQuery = entityManager.createQuery(criteriaQuery);
for (Map.Entry<String, String> entry : filters.entrySet()) {
    if (entry.getKey().equalsIgnoreCase("discountId")) {
        ParameterExpression<Long> parameterExpression = criteriaBuilder.parameter(Long.class);
        predicates.add(criteriaBuilder.equal(root.get(Discount_.discountId), parameterExpression));
        typedQuery.setParameter(parameterExpression, Long.parseLong(entry.getValue().trim()));
    }
    //...The rest of the if-else-if ladder.
}
//...
//...
//...
Long count = typedQuery.setFirstResult(first).setMaxResults(pageSize).getSingleResult();
这样做会导致java.lang.IllegalArgumentException: Name of parameter to locate cannot be null抛出异常.
| 归档时间: | 
 | 
| 查看次数: | 6035 次 | 
| 最近记录: |