我有一个表单,用户可以在其中选择搜索条件。
标准是:
Product Name: Input field
Name Option: Radio button group - begins with (default selected)/ is/ contains
Country: dropdown of country
Status: All, Active, Blocked
Type: All, One, Two, Three
仅限产品名称。其他下拉列表是可选的。
因此,如果没有国家,我应该找到所有国家的产品。 如果没有给出活动,我应该找到活动和被阻止的产品。 如果没有给出Type,我应该返回所有三种类型的产品。
我正在构建hibernate查询,如下所示:
String productName = searchCriteria.getValue("productName");
String productNameCriteria = searchCriteria.getValue("productNameCriteria");
String country = searchCriteria.getValue("country");
String status = searchCriteria.getValue("status");
String type = searchCriteria.getValue("type");
Query prodQuery = null;
String prodSql = "select count(*) from Product p where";
// is
if (productNameCriteria.equalsIgnoreCase("IS")){
prodSql += "p.productName = '"+productName+"'";
}
// begins with
else if (productNameCriteria.equalsIgnoreCase("BEGINS WITH")){
prodSql += "p.productName = '"+productName+"%'";
}
// contains
else (productNameCriteria.equalsIgnoreCase("BEGINS WITH")){
prodSql += "p.productName = '%"+productName+"%'";
}
if(!country.equalsIgnoreCase("0")){
prodSql += " and p.country = '"+country+"'";
}
if(!status.equalsIgnoreCase("ALL")){
if(status.equalsIgnoreCase("active"))
prodSql += " and p.status = 'active'";
else
prodSql += " and p.status = 'blocked'";
}
if(!type.equalsIgnoreCase("ALL")){
if(type.equalsIgnoreCase("one"))
prodSql += " and p.type = 'one'";
else if(type.equalsIgnoreCase("two"))
prodSql += " and p.type = 'two'";
else
prodSql += " and p.type = 'three'";
}
prodQuery = this.em.createQuery(prodSql);
List<Object[]> results = prodQuery.getResultList();
我正在以正确的方式构建查询吗?还是有其他有效的方法???
感谢阅读!!
答案 0 :(得分:4)
尝试查看Criteria Query
Criteria crit = sess.createCriteria(Product.class);
if (productNameCriteria.equalsIgnoreCase("IS"))
crit.add( Restrictions.eq("productName", productName);
else if (productNameCriteria.equalsIgnoreCase("BEGINS WITH"))
crit.add( Restrictions.like("productName", productName + "%")
// etc
如果您绝对必须构建字符串查询,那么您应该使用StringBuilder
StringBuilder sb = new StringBuilder();
sb.append("select count(*) from Product p where ");
if (productNameCriteria.equalsIgnoreCase("IS"))
sb.append("p.productName = '").append(productName).append("'");
// etc
String query = sb.toString();
使用StringBuilder
可减少在运行时创建的实例数。
您还可以考虑使用查询参数,这会降低一些查询复杂性,但我不知道运行时查询性能的影响是什么。
"select count(*) from Product p where p.productName = :productName"
"select count(*) from Product p where p.productName = ?"
然后,您可以使用Query#setParameter
(或setString
之类的其他变体之一)来定义查询中的值。这也是构建查询的一种更好的方法,因为它将自动管理您从UI接收的值的引用和转义。 使用查询参数而不是字符串连接,无论您如何构建查询字符串。
答案 1 :(得分:2)
是的。如果你以这种方式动态构建查询,它将会工作。但是代码将变得乏味和嘈杂,因为它涉及到where-condition子句的字符串操作。
对于这种查询的用例,这是一种允许用户使用 Query By Example 指定返回结果集匹配的不同属性值范围的搜索(QBE)更有效率和优雅。
QBE的想法是,您提供查询类的实例,并初始化一些属性,查询将返回具有匹配属性值的记录。
参考