Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate query building based on conditions

I have a form where user can select search criteria.

The criterias are say:

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

Only Product Name is mandatory. Other dropdowns are optional.

So if country is not given, I should find products for all countries. If active is not given, I should find both active and blocked products. If Type is not given, I should return all the three types products.

I am building hibernate query as below:

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

Am I doing query building the right way ? Or is there any other efficient method ???

Thanks for reading!!

like image 368
Vicky Avatar asked Nov 18 '11 07:11

Vicky


People also ask

How do I create a criteria query in Hibernate?

The Hibernate Session interface provides createCriteria() method, which can be used to create a Criteria object that returns instances of the persistence object's class when your application executes a criteria query.

How can we get all records using criteria in Hibernate?

JPQL provides a simple and straightforward way to get all entities from a table. Our Hibernate session's createQuery() method receives a typed query string as the first argument and the entity's type as the second. We execute the query with a call to the getResultList() method which returns the results as a typed List.

Can you explain criteria in Hibernate?

The Hibernate Criteria Query Language (HCQL) is used to fetch the records based on the specific criteria. The Criteria interface provides methods to apply criteria such as retreiving all the records of table whose salary is greater than 50000 etc.

What is the difference between query and criteria in Hibernate?

HQL is suitable for executing Static Queries, where as Criteria is suitable for executing Dynamic Queries. HQL is to perform both select and non-select operations on the data, Criteria is only for selecting the data, we cannot perform non-select operations using criteria.


1 Answers

Try looking at 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

If you absolutely must build a string query then you should be using a 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();

Using a StringBuilder reduces the number of instances created at runtime.

You could also look into using query parameters, which would reduce some of the query complexity, though I don't know what the runtime query performance effects are.

"select count(*) from Product p where p.productName = :productName"
"select count(*) from Product p where p.productName = ?"

You can then use Query#setParameter (or one of the other variants like setString) to define the values in the query. This is also a much, much better way of building the query because it's going to automatically manage quoting and escaping of values you're receiving from the UI. Use query parameters and not string concatenation, regardless of how you build the query string.

like image 97
ptomli Avatar answered Oct 05 '22 11:10

ptomli