I have the following code snippet for building criteria builder where condition.
Would like to know are there any ways of making this better as I would have more where conditions and same conditions will be used for getting count of records.
Any insight is highly appreciable
private List <Product> getProducts(MultivaluedMap params) throws JSONException {
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery <Product> criteriaQuery = criteriaBuilder.createQuery(Product.class);
Root <Product> root = criteriaQuery.from(Product.class);
List <Predicate> p = new ArrayList <Predicate> ();
Predicate prodIdPredicate, prodNamePredicate;
JSONObject inputJSON = new JSONObject(params);
if (inputJSON.isNull("filter") == false) {
JSONObject filter = inputJSON.getJSONObject("filter");
JSONArray filters = filter.getJSONArray("filters");
for (int i = 0; i < filters.length(); i++) {
JSONObject j = (JSONObject) filters.get(i);
if (j.getString("field").equals("prodId")) {
prodIdPredicate = criteriaBuilder.like(root.get(Product_.prodId), j.getString("value"));
p.add(prodIdPredicate);
}
if (j.getString("field").equals("prodName")) {
prodNamePredicate = criteriaBuilder.like(root.get(Product_.prodName), j.getString("value"));
p.add(prodNamePredicate);
}
}
}
Predicate[] pr = new Predicate[p.size()];
p.toArray(pr);
criteriaQuery.where(pr);
First of all you must consider to restructure your application in a layered manner. You at least need 3 layer, DAO, Service and WebService.
All the things about database and JPA must be in your DAO layer. And all the json related things must be in your WebService layer. Your service layer must manage the transaction and the communication between web service and dao layer.
First lets talk about your Web Service layer. Your JSON objects probably come from a Restful web service. Since almost all the frameworks supports json marshalling/unmarshalling it is not wise to parse your data transfer objects manually. By this I mean, you may prefer to declare a FieldDto class and pass its instances around instead of JSONObject. Here is an example of
FieldDto
. It is a POJO.You can easily marshall/unmarshall to json using GSON or Jackson. Probably your framework has one of these on default to handle json conversion.
Next layer is Service layer. In service layer you manage your transactions and convert your DTO objects to something that your DAO layer can easily understand. In this case your service layer pass
fieldDto.getProdId()
andfielDto.getProdName()
to DAO layer.Your last layer is DAO layer. First lets change your method signature.
This is not it. This code still needs improvement. In one of my projects, I create a fluent api to manage all the boilerplate parts. When you start to write other DAO classes you will realise that some of the code blocks repeats over and over again.
Here is an example of a fluent api. You may want to construct your version of it.
If you use this. Than your method become this.
It will be better if you write your own SimpleSelectBuilder to handle boilerplate code blocks and increase reusability. For example you need to add
like
statement to code above.Managing all the layers, transactions, connection-pools etc will take your time a lot. Instead you may want to consider a middleware to manage all of this for your. In my projects I prefer Spring.