Ricardo Umpierrez
Ricardo Umpierrez

Reputation: 768

Multiple Create Criteria re-use code grails

I have a create criteria using multiple params with pagination. The issue that I´m having that if is possible to re-use the code inside the and for others create-criteria totally differents, witouth having to duplicate the code. I reffer that if I have the cases createcriteria and want to do the same "filters" on the cases2 not have to duplicate the code, unify both createCriteria is not an option Per example, the problem that I´m facing is that one needs to be with pagination, and other don´t need to be, and both needs to access distinct fields, so the unique option is to create two identical create criteria if I´m not missing something. That is a example, that cases is at least 90% indetically to cases2, and what would be a good mode to reuse the code?

 def cases = PpCase.createCriteria().list{ 
            and{
                if(limit){
                    maxResults(limit)
                }
                firstResult(offset)
                order("mostRecentPaymentDate", "desc")
                order("totalAmount", "desc")
                if(params.admin_id){
                    eq("adminId",params.admin_id)
                }
                if(params.status){
                    eq("status",params.status.toUpperCase() as PpCase.Status)
                }
                if(params.date_from){
                    ge('dateCreated', Date.parse("yyyy-MM-dd",params.date_from))
                }
                if(params.date_to){
                    le('dateCreated', Date.parse("yyyy-MM-dd",params.date_to))
                }
                if(params.date_closed_from){
                    ge('closedDate', Date.parse("yyyy-MM-dd",params.date_closed_from))
                }
                if(params.date_closed_to){
                    le('closedDate', Date.parse("yyyy-MM-dd",params.date_closed_to))
                }
        }
}

def cases2 = PpCase.createCriteria().list{ 
            and{
                firstResult(offset)
                order("mostRecentPaymentDate", "desc")
                order("totalAmount", "desc")
                if(params.admin_id){
                    eq("adminId",params.admin_id)
                }
                if(params.status){
                    eq("status",params.status.toUpperCase() as PpCase.Status)
                }
                if(params.date_from){
                    ge('dateCreated', Date.parse("yyyy-MM-dd",params.date_from))
                }
                if(params.date_to){
                    le('dateCreated', Date.parse("yyyy-MM-dd",params.date_to))
                }
                if(params.date_closed_from){
                    ge('closedDate', Date.parse("yyyy-MM-dd",params.date_closed_from))
                }
                if(params.date_closed_to){
                    le('closedDate', Date.parse("yyyy-MM-dd",params.date_closed_to))
                }
        }
}

More real example: In cases I need some fields, but with a limit , and in cases2 I need distinct fields, and witouth a limit,I´m duplicating the 90% of the code.

     def cases = PpCase.createCriteria().list{ 
                projections {
                    sum("field1")
                    countDistinct("id")
                }
              and{
               if(limit){
                    maxResults(limit)
                }
           //HERE SHOULD BE THE CODE THAT I NEED TO REUTILIZE
 }
 def cases2 = PpCase.createCriteria().list{ 
                projections {
                    sum("field2")
                    countDistinct("id")
                }
              and{

           //HERE SHOULD BE THE CODE THAT I NEED TO REUTILIZE
 }

Upvotes: 2

Views: 1667

Answers (3)

Burt Beckwith
Burt Beckwith

Reputation: 75671

I'd use "where" queries, which use DetachedCriteria under the hood, or DetachedCriteria directly. where queries don't run until you call list/get/count/exists/deleteAll/updateAll, so they're great candidates for composing queries in parts. Named queries can similarly be composed, but they need to be complete, runnable queries, but a partial where query is fine as long as you add the missing parts via composition before running them. They're also more flexible since you can use them to delete and update.

Upvotes: 3

Poundex
Poundex

Reputation: 410

I'm not sure what you mean when you say "unify both createCriteria is not an option", especially considering in the code above you are executing the exact same query twice and ending up with two lists containing the same rows.

One way to reuse your criteria is to just define the criteria as a seperate closure, and pass that to createCriteria.

Closure fetchPayments = { 
        and{
            if(limit){
                maxResults(limit)
            }
            firstResult(offset)
            order("mostRecentPaymentDate", "desc")
            order("totalAmount", "desc")
            if(params.admin_id){
                eq("adminId",params.admin_id)
            }
            if(params.status){
                eq("status",params.status.toUpperCase() as PpCase.Status)
            }
            if(params.date_from){
                ge('dateCreated', Date.parse("yyyy-MM-dd",params.date_from))
            }
            if(params.date_to){
                le('dateCreated', Date.parse("yyyy-MM-dd",params.date_to))
            }
            if(params.date_closed_from){
                ge('closedDate', Date.parse("yyyy-MM-dd",params.date_closed_from))
            }
            if(params.date_closed_to){
                le('closedDate', Date.parse("yyyy-MM-dd",params.date_closed_to))
            }
    }
}

def cases  = PpCase.createCriteria().list(fetchPayments)
def cases2 = PpCase.createCriteria().list(fetchPayments)

Upvotes: 2

praveen_programmer
praveen_programmer

Reputation: 1062

You can do this by using named query : have look to documentation .namedQueries

Upvotes: 2

Related Questions