Search code examples
grailscriteriahibernate-criteria

How can I put an if statement inside of a createCriteria in grails?


I'm new in grails and I have a problem. I have a method that receive some data and match the data with a createCriteria and return the data. It's working fine, but that I want to do now if match with the five params that I have in the method and if match return the data, if not match with the five params, try if match with four params and return the data, if not match with the four params, try if match with three and return the data....

But not really sure how can I put all this in a if statement and return my result.dataPerson or maybe I have to find another way to do it.

My method:

def getPersonData(String name, String surname, String address, String phone){


    def searchdataPerson = ClientConfig.createCriteria()
    def result = searchdataPerson.get{
        and{
            or{
                eq('surname', surname)
                isNull('surname')
            }
            or{
                eq('address', address)
                isNull('address')
            }
            or{
                eq('phone', phone)
                isNull('phone')
            }
            or{
                eq('name', name)
                isNull('name')
            }
        }
        maxResults(1)
    }

    return result.dataPerson
}

I'm trying to do something like this but it doesn't work

def searchdataPerson = ClientConfig.createCriteria()
        def result = searchdataPerson .get{
            if(eq('name', name) && eq('surname', surname) && eq('address', address) && eq('phone', phone)){
            }else if(eq('name', name) && eq('surname', surname) && eq('address', address)){
            }       
            maxResults(1)
        }
return result.dataPerson

I get this error:

java.lang.NullPointerException: Cannot get property 'dataPerson' on null object

Solution

  • As Jeff has pointed out above you should really refer to result and you are getting the error because you are getting a result but then trying to return an entity or maybe event object hanging off the result.

    What is dataPerson ? is it a relationship hanging off of ClientConfig i.e belongsTo or hasMany declaration in ClientConfig ?

    From all of above it isn't exactly clear but to try and explain it another way, you could use HQL:

    String  query="""
    select new map(c.name as name,c.surname as surname, d as dataPerson)
     from ClientConfig c 
    
    
    left join c.dataPerson d where 
    
    (c.surname != 'GooglyMoogly' or c.surame is null or c.surname=:surname) and
    
    (c.address != 'Caddyshack' or c.address is null or c.address=:address) and
    
    (c.phone is null or c.phone=:phone) and
    (c.name is null or c.name=:name) and
    
    """
    def inputParams=[surname:surname,address:address,phone:phone,name:name]
    
           def result =  ClientConfig.executeQuery(query,inputParams,[readOnly:true,timeout:15,max:1])
    
        result?.each { output ->
    
      println "--- ${output?.name} ???? ${output.surname} ???? "
    
       output?.dataPerson.each { dp ->
          println "--- ${dp.name} ???? "
       }
    }
    

    Some of above may not be correct but may help you decipher what it is you are trying to achieve.

    In the above HQL statement I have done a left join between clientConfig and dataPerson. This is assuming

    class ClientConfig {
    
       static hasMany= [dataPerson:DataPerson]
    }
    

    The left join will mean even when dataPerson does not exist it will attempt to join the (null object)

    When iterating if all I wanted was the aspects hanging off of dataPerson then

     result?.each { output ->
       // if hasMany
         println "${output.dataPerson[0].name}"
       // if a belongsTo or a direct relation:
         println "${output.dataPerson.name}"
    }
    

    And to save on doing any of this if you define the actual elements you wish to collect in your HQL then your final iteration will only consist of what it is you asked for exactly and then there is no need to forward walk through the class.

    String  query="""
        select new map(d.name as name,d.surname as surname, d.address as address)
         from ClientConfig c 
    ...
    

    You now have objects here no need to expand from result to result.dataSet ....:

     result?.each { output ->
       println " $output.name $output.surname $output.address "
        }