Grails GORM count function in a named query - grails

I'm writing some named queries for my domain classes in Grails and I've hit a blocker.
Given the following domain class:
class Contributor {
// evals is a collection of another domain class
def evals
static namedQueries = {
hasNoEvals {
// Something like this...
evals.size() == 0
}
}
}
Can anyone help with the syntax I need to select the Contributors who have no Evals?
Thanks.

Please look in createCriteria doc for "collection property" operations. In your case, it is isEmpty:
static namedQueries = {
hasNoEvals {
isEmpty('evals')
}
}
For generic size restriction, it is sizeEq, sizeLe and so on.

Related

How can I get objects based off of certain associations?

I have the following domain classes (Only trying to show what is needed to get the idea) :
class Scholarship {
static hasMany = [grades:Grade]
}
and
class Grade {
String id
String description
}
In words I would like to, "Get all scholarships where the associated grade_id = myId". I would like to accomplish this using grails domain classes and not using sql. Any help appreciated
Are you looking for something like this?...
def results = Scholarship.withCriteria {
grades {
// myId must be defined somewhere above...
idEq myId
}
}
EDIT
A comment below adds to the original question and asks what if another relationship was expressed like this...
class Scholarship {
static hasMany = [grades:Grade,majors:Major]
}
The query I show above would still be exactly the same. The fact that there is a majors collection would not be relevant unless you wanted to include some attribute of Major to also be part of the criteria, which could look something like this...
def results = Scholarship.withCriteria {
grades {
// myId must be defined somewhere above...
idEq myId
}
majors {
// only return Scholarship instances which
// contain a Major with the name 'Mechanical Engineering'
eq 'name', 'Mechanical Engineering'
}
}
I hope that helps.

Sorting domain class properties with respect to another domain class properties

I've two domain classes
1.CustomerInterest.groovy
static hasMany = [activities:Activity]
static belongsTo=[customer:Customer,projectProperty:ProjectProperty]
static mapping={
activities sort:'dateCreated',order:'desc'
}
2.Activity.groovy
Date dateCreated
static belongsTo = [customerInterest:CustomerInterest, employee:Employee]
In a controller i am doing this..
def customerDetails(Customer customer)
{
def customerInterest=customer.customerInterests
render view:"customerDetails",model:[customerInterest:customerInterest]
}
customerDetails.gsp
<g:each in="${customerInterest}" var="ci">
${ci}
</g:each>
**
Question: I want to sort CustomerInterest on property dateCreated of Activity domain.
**
Any help as soon as possible would be appreciated.
Try this
def customerInterest=customer.customerInterests.sort { it.activities.dateCreated }
Instead of using the sort order in the mappings definition, you can use the old java Comparable-interface:
class Foo implements Comparable {
int compareTo(anotherObject) {
// complex logic returning -1 or 0 or 1
}
}
Then you can call listOfFoos.sort() and it will sort it with the help of the compareTo-method.
Beware that (equals) == will also use this method, so ensure that (only) identical objects will return 0.

Using named queries

I have a named query in a domain class:
class Store {
static namedQueries {
openOnWeekends {
// some conditions here...
}
}
}
I know that I can do Store.openOnWeekends.list(), but I want to do something like this:
def pickupWeekendStores = Order.get(params.id).books.store.openOnWeekends
Is there a way to use named queries like that? Any suggestions on how to get the stores open on weekends?
Edit:
Order hasMany Book, Book hasMany Store
Named queries support additional criteria at invocation, so you could try:
Store.openOnWeekends {
books {
'in'('id', Order.get(params.id).books.collect { it.id })
}
}
Does doing something like:
Set<Store> pickupWeekendStores = Order.get(params.id).books*.store.collect { it.openOnWeekends.list() }
work?

Transient property in Grails domain

I have a Grails domain called People, and I want to check that each People has childs or not. Childs are other People objects. Here is my domain structure:
class People implements Serializable {
static constraints = {
name (nullable : false, unique : true)
createdBy (nullable : false)
creationDate (nullable : false)
}
static transients = ['hasChild']
static mapping = {
table 'PEOPLE'
id generator: 'sequence', params : [sequence : 'SEQ_PK_ID']
columns {
id column : 'APEOPLE_ID'
parentPeople column : 'PARENT_PEOPLE_ID'
}
parentPeople lazy : false
}
People parentPeople
String name
String description
Boolean hasChild() {
def childPeoples = People.createCriteria().count {
eq ('parentPeople', People)
}
return (childPeoples > 0)
}
}
But I cannot call people.hasChild() at anywhere. Could you please helpe me on this? Thank you so much!
It's because in eq ('parentPeople', People), Grails can't understand what "People" is (it's a class). You should replace "People" by this. For example:
static transients = ["children"]
def getChildren() {
def childPeoples = People.findAllByParentPeople(this, [sort:'id',order:'asc'])
}
Another way to get the same result is to use Named Queries. It seems more concise and was created specifically for this purpose. I also like it because it fits the pattern of static declarations in a domain model and it's essentially a criteria, which I use throughout my applications. Declaring a transient then writing a closure seems a bit of a work-around when you can declare named queries ... just my opinion.
Try something like this:
static namedQueries = {
getChildren {
projections {
count "parentPeople"
}
}
}

Defining default sort-order in Grails/GORM

Let's say I have definied a User object using GORM. Each user can have zero or more Login:s. Each Login has a timestamp. When retrieving user.logins I want the logins to be sorted based on the value of login.date. What is the correct Grails way to achieve this?
Example: I want the following code to list all the user's logins in ascending order.
<g:each var="login" in="${user.logins}">
<tr>
<td>${login.date}</td>
</tr>
</g:each>
These are the referenced classes:
class User {
...
def hasMany = [logins: Login]
static fetchMode = [logins: "eager"]
}
class Login {
Date date
...
def belongsTo = [User]
}
I'm running Grails 1.0.4 which is the latest stable release.
They show how to do this on the GORM page in the reference guide (section 5). The bit you want is near the bottom of that document is the section you want. They have two simple examples:
class Airport {
…
static mapping = {
sort "name"
}
}
class Airport {
…
static mapping = {
sort name:"desc"
}
}
They also have an example of sorting on an association:
class Airport {
…
static hasMany = [flights:Flight]
static mapping = {
flights sort:'number'
}
}
Just make the Login Class implement the Comparable interface:
class Login implements Comparable {
// ...
Date date
public int compareTo(def other) {
return date <=> other?.date // <=> is the compareTo operator in groovy
}
}
and declare the relation to be a SortedSet:
class User {
...
def hasMany = [logins: Login]
SortedSet logins
static fetchMode = [logins: "eager"]
}
The handling of default sort order in Grails/GORM seems to have been radically simplified in Grails 1.1:
Grails 1.1 release notes (search for "Default Sort Order")

Resources