I have a table called employee and child table address.
Now I want to get a list of employees sort by address1 in address table using GORM.
Employee.findAllByName(name, [max: maxRecords, offset: 100,sort: Address.address1, order: desc])
the above statement is not working, any suggestions would be appreciated.
Thanks
Try using a criteria query like so...
def c = Employee.createCriteria()
def results = c.list (max: maxRecords, offset: 100) {
eq("name", name)
address {
order("addres1", "desc")
}
}
This works for me!
Another option is to add a default sort order like so...
class Address{
…
static mapping = {
sort address1:"desc"
}
}
However, I always prefer to do things as an 'as-needed' basis rather than define that sorting be done every time even when it may not be needed. U pick. Enjoy!
Related
I am using grails-2.5.6 version. I am using spring-security-core plugin. I have a criteria query on UserRole table. Where I want to find all distinct users by a role. It is working properly.
But the problem is the pagination effect. When I am counting on the list it is counting on UserRole list object. But I need the count on distinct projection items. Here is my attempt below:
def list(Integer max) {
def userInstanceList = UserRole.createCriteria().list(params) {
createAlias('user', 'au')
createAlias('role', 'ar')
projections {
distinct("user")
}
if (params.roleId) {
eq('ar.id', params.getLong("roleId"))
}
}
def totalCount = userInstanceList.totalCount
[userInstanceList: userInstanceList, totalCount: totalCount]
}
Here, totalCount is the number of UserRole list. But I want the distinct projection count.
I would tackle this slightly differently, you want to analyse the users, not the userroles.
So I'd do something like:
List<User> usersWithRole = UserRole.createCriteria().list(params) {
role {
eq('id', params.getLong("roleId"))
}
}*.user
int count = usersWithRole.size()
Unless of course there's hundreds or thousands of users, in which case I wouldn't want to load all of them each time and would revert to SQL.
Is this a custom version of spring security you're using? I've never seen Roles with a 'long' based ID, usually, the key is a String representing the Authority name.
Usually the DBAs see the use of distinct keyword as a code-smell.
In your case I would rather use the User as the main domain object to run the query against and a group by clause:
long id = params.getLong "roleId"
def list = User.createCriteria().list( params ) {
projections{
groupProperty 'userRole.role.id'
}
if( id )
userRole{
role{
eq 'id', id
}
}
}
I am creating a basic CRUD application with a Person entity:
class Person {
public int Age;
...
public int getAge() {
return this.Age;
}
public void setAge(int AgeToSet) {
this.Age = AgeToSet;
}
}
I have a controller and I want to retrieve all Persons with an age of 20:
def filter = {
def c = Person.createCriteria();
def persons = c.list{
eqProperty("Age", "20");
}
[persons: persons];
}
But this is not working and is, instead, giving me the error:
ERROR StackTrace - Full Stack Trace:
org.hibernate.QueryException: could not resolve property: Age of: project.Person
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:62)
What could be the problem?
Three things:
Your Age needs to start with lowercase: age.
Your criteria is wrong, you want to use eq. eqProperty compares two properties, but you only need one and a value.
Your comparision must be with an int, like this: eq("myage", 20).
Since this query is so simple, you may want to just use a DynamicFinder: http://gorm.grails.org/6.0.x/hibernate/manual/index.html#finders
With a Dynamic Finder, you could simplify the query to:
def persons = Person.findAllByAge(20)
Just a suggestion. I use Dynamic Finders as my primary query method. If I need a query that is more complex, I'll resort to a .createCriteria and then a .executeQuery which takes HQL.
I am using Grails 2.2.4 and having one Domain contains value as map and I want to find domain object using key of map. Please help me to resolve this issue.
Student.groovy
package com.grails
import java.util.Map;
class Student {
String firstName
String lastName
Map address
static constraints = {
}
}
When My application are run I can see that Grails application create tables in database are as follow:
1) first table
student
id
version
first_name
last_name
indexes
2) second table
student_address
address
addres_idx
addres_elt
When I save Domain as:
def std = new Student()
std.firstName = 'Piyush'
std.lastName = 'Chaudhari'
std.address = [city:'Surat',state:'Gujarat',pincode:'38001']
std.save(flash:true)
values are insert in database as follow:
student table
ID VERSION FIRST_NAME LAST_NAME
1 0 Piyush Chaudhari
student_address table
ADDRESS ADDRESS_IDX ADDRESS_ELT
1 city Surat
1 state Gujarat
1 pincode 38001
Now, I want data or row using GORM like Student.findBy_____ or Student.findAllBy______
where 'city' = surat
Any one can help me to resolved this issue?
You can use:
Student.findBy<FieldName1>And<FieldName2> (<FieldNameParameter1>, <FieldNameParameter2>)
Or Either:`
Student.list().find { it.address.city == 'Surat' }
Student.list().findAll { it.address.city == 'Surat' }
`
I don't think that you can search things like this using maps.
Maybe you can do this:
def students = Student.list()
def result = students.each { student -> student.address.city == 'Surat' }
println("Resultado" + result)
But this is a very bad way to do this kind of things
Define an address class, and then add an address field to the student class (this will change how your tables are mapped in the database):
class Student {
String firstName
String lastName
Address address
static constraints = {
}
}
class Address {
String city
String state
String pincode
}
Address should be another entity in your domain, not a map of values. Remember that Grails GROM is an ORM, so you should design your domain using a OOP model in order to take advantage of the dynamic finders and criterias for doing queries.
With those changes in place, you can now use a simple criteria:
def students = Student.withCriteria{
'address'{
eq('city', 'surat')
}
}
More information about criterias in the grails docs:
http://grails.org/doc/latest/ref/Domain%20Classes/withCriteria.html
http://grails.org/doc/latest/guide/single.html#criteria
If you want to use Dynamic finders, you will have to get all the address with city = 'surat' and then use a findByAddressInList(...). But i think that in this case, criterias is a better approach
I'm relatively new to Grails.
I have the following
class House {
Integer number
Integer maxResidents
static belongsTo = [town: Town]
}
class Town {
String name
static hasMany = [houses: House]
}
I want to get five towns with most Houses. I have seen the possibility to create a criteria but I can't deal with it now. Can someone support?
Thank you!
As you have a bidirectional association you can do this with a query on House:
def result = House.withCriteria {
projections {
groupProperty("town", "town")
rowCount("numHouses")
}
order("numHouses", "desc")
maxResults(5)
}
This would return you a list of results where each result res has the town as res[0] and the number of houses as res[1]. If you'd prefer each result to be a map giving access to res.town and res.numHouses then you should add
resultTransformer(AliasToEntityMapResultTransformer.INSTANCE)
after the maxResults line (along with the appropriate import at the top of your file).
I am using Nimble and Shiro for my security frameworks and I've just come accross a GORM bug. Indeed :
User.createCriteria().list {
maxResults 10
}
returns 10 users whereas User.list(max: 10) returns 9 users !
After further investigations, I found out that createCriteria returns twice the same user (admin) because admin has 2 roles!!! (I am not joking).
It appears that any user with more than 1 role will be returned twice in the createCriteria call and User.list will return max-1 instances (i.e 9 users instead of 10 users)
What workaround can I use in order to have 10 unique users returned ?
This is a very annoying because I have no way to use pagination correctly.
My domain classes are:
class UserBase {
String username
static belongsTo = [Role, Group]
static hasMany = [roles: Role, groups: Group]
static fetchMode = [roles: 'eager', groups: 'eager']
static mapping = {
roles cache: true,
cascade: 'none',
cache usage: 'read-write', include: 'all'
}
}
class User extends UserBase {
static mapping = {cache: 'read-write'}
}
class Role {
static hasMany = [users: UserBase, groups: Group]
static belongsTo = [Group]
static mapping = { cache usage: 'read-write', include: 'all'
users cache: true
groups cache: true
}
}
Less concise and clear, but using an HQL query seems a way to solve this problem. As described in the Grails documentation (executeQuery section) the paginate parameters can be added as extra parameters to executeQuery.
User.executeQuery("select distinct user from User user", [max: 2, offset: 2])
this way you can still use criteria and pass in list/pagination paramaters
User.createCriteria().listDistinct {
maxResults(params.max as int)
firstResult(params.offset as int)
order(params.order, "asc")
}
EDIT: Found a way to get both! Totally going to use it now
http://www.intelligrape.com/blog/tag/pagedresultlist/
If you call createCriteria().list() like this
def result=SampleDomain.createCriteria().list(max:params.max, offset:params.offset){
// multiple/complex restrictions
maxResults(params.max)
firstResult(params.offset)
} // Return type is PagedResultList
println result
println result.totalCount
You will have all the information you need in a nice PagedResultList format!
/EDIT
Unfortunately I do not know how to get a combination of full results AND max/offset pagination subset in the same call. (Anyone who can enlighten on that?)
I can, however, speak to one way I've used with success to get pagination working in general in grails.
def numResults = YourDomain.withCriteria() {
like(searchField, searchValue)
order(sort, order)
projections {
rowCount()
}
}
def resultList = YourDomain.withCriteria() {
like(searchField, searchValue)
order(sort, order)
maxResults max as int
firstResult offset as int
}
That's an example of something I'm using to get pagination up and running. As KoK said above, I'm still at a loss for a single atomic statement that gives both results. I realize that my answer is more or less the same as KoK now, sorry, but I think it's worth pointing out that rowCount() in projections is slightly more clear to read, and I don't have comment privileges yet :/
Lastly: This is the holy grail (no pun intended) of grails hibernate criteria usage references; bookmark it ;)
http://www.grails.org/doc/1.3.x/ref/Domain%20Classes/createCriteria.html
Both solutions offered here by Ruben and Aaron still don't "fully" work for pagination
because the returned object (from executeQuery() and listDistinct) is an ArrayList
(with up to max objects in it), and not PagedResultList with the totalCount property
populated as I would expect for "fully" support pagination.
Let's say the example is a little more complicated in that :
a. assume Role has an additional rolename attribute AND
b. we only want to return distinct User objects with Role.rolename containing a string "a"
(keeping in mind that a User might have multiple Roles with rolename containing a string "a")
To get this done with 2 queries I would have to do something like this :
// First get the *unique* ids of Users (as list returns duplicates by
// default) matching the Role.rolename containing a string "a" criteria
def idList = User.createCriteria().list {
roles {
ilike( "rolename", "%a%" )
}
projections {
distinct ( "id" )
}
}
if( idList ){
// Then get the PagedResultList for all of those unique ids
PagedResultList resultList =
User.createCriteria().list( offset:"5", max:"5" ){
or {
idList.each {
idEq( it )
}
}
order ("username", "asc")
}
}
This seems grossly inefficient.
Question : is there a way to accomplish both of the above with one GORM/HQL statement ?
You can use
User.createCriteria().listDistinct {
maxResults 10
}
Thanks for sharing your issue and Kok for answering it. I didn't have a chance to rewrite it to HQL. Here is my solution (workaround): http://ondrej-kvasnovsky.blogspot.com/2012/01/grails-listdistinct-and-pagination.html
Please tell me if that is useful (at least for someone).