Dynamically creating a query based on params being passed to a controller

谁说胖子不能爱 提交于 2020-01-01 11:41:47

问题


In my task management application, users should be able to filter tasks based on : assignedTo, priority, status and/or dueDate

I am not sure on how to create a dynamic query in that it will build a query based on the available parameters.

For example :

If I have a URL such as : task/index?assignedTo=1&status=2

I can build a query based on only these two parameters. The method I am used to is the

Task.findAllByAssignedToAndStatus(
   User.get(params.assignedTo),
   TaskStatus.get(params.status)
)

I obviously dont want to implement a DRY method by writing out each findAllBy query for every possible URL parameter combination.

Is there a good way to do this in grails?


回答1:


We have implemented filter functionality on the domain classes to do this. In short you add small snippets of namedQueries to your domain class.

Example:

class Employee {

    String firstname
    String lastname
    Integer age

    static constraints = {
    }

    static namedQueries = {
        filteronFirstname { String inFirstname ->
            if (inFirstname&& inFirstname?.size() > 0) {
                ilike 'firstname', "%${inFirstname}%"
            }
        }

        filteronLastname { String inLastname ->
            if (inLastname && inLastname?.size() > 0) {
                ilike 'lastname', "%${inLastname}%"
            }
        }

        filteronAgeOlderThen { String ageOlderThen ->
            if (age && age ?.size() > 0) {
                gt 'age', ageOlderThen as Integer
            }
        }

    }
}

This enable fine grained filter capabilities so you can build 1 list method that uses all filter methods and depending on what the user gives as input the namedqueries are joined together.

Employee.filteronFirstname("John").
filterOnLastname("Doe").
filteronAgeOlderThen("10").
list(params)



回答2:


I managed to get this working using createCriteria as follows :

I am using the value 0 for any of the params if the user selects 'All' for that particular filter, therefore it will be omitted from the where clause, ie no eq() statement for that parameter.

A snippet of the code:

else
    {       
        def assignedTo = Integer.parseInt(taskParams.assignedTo)
        def priority = Integer.parseInt(taskParams.priority)
        def status = Integer.parseInt(taskParams.status)

        tasks = Task.createCriteria().list {            

            eq("project", Project.get(taskParams.PId))

            if(assignedTo > 0)
                eq("assignedTo", User.get(assignedTo))

            if(priority > 0)
                eq("priority", TaskPriority.get(priority))

            if(status > 0)
                eq("status", TaskStatus.get(status))                
        }           
    }
    return tasks
}



回答3:


I would consider the Searchable Plugin for this (http://grails.org/plugin/searchable). It is easy to specify which properties of Task should be searchable.




回答4:


Take a look at fluent interfaces, you can use these to add or remove (filter) each parameter.

http://en.wikipedia.org/wiki/Fluent_interface




回答5:


My solution for a dynamic Where query from URL:

if (params.query) {
    def classLoader = getClass().getClassLoader();
    def query = new GroovyShell(classLoader).evaluate(
            "import myapp.Visit; Visit.where {$params.query}")
    visits = query.list(params)
} 

This takes its constraints from an URL like this:

visit/index?query=client.status=='suspect';atHome==false


来源:https://stackoverflow.com/questions/15947481/dynamically-creating-a-query-based-on-params-being-passed-to-a-controller

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!