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")
Related
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.
I am trying to write a query in Grails to return a set of results from a domain class, but within those return the relevant results of a separate class whom have the parentId of the main class.
def query = Cars.where {
(colour == 'red')
}
And then within each list item include the set of parts relating to that CAR ID (as an example of what I'm trying to achieve, I know the code is incorrect though....
query.each{
this car. add(Parts.whereCarID{it.id})
}
If you define your domain model properly, you should get it without a criteria involved.
As far as I understand you need to add static hasMany = [parts: Parts] in your Cars domain class, and static belongsTo = [car:Cars] in your Parts class.
So for example, here how it might look:
class Cars {
string colour
static hasMany = [parts:Parts]
// ... rest of your properties
}
class Parts {
static belongsTo = [car:Cars]
// ... rest of your properties
}
And to get your result just do this:
def cars = Cars.findAllByColour('red')
Then you can do:
cars.each { car->
println car.parts // <-- all the parts for each car is here
}
I read that a m:m relationship often means there is a third class that isn't yet required. So I have m:m on User and Project, and I created a third domain class, ProjectMembership
The three domains are as follows (minimized for illustration purposes):
User
class User {
String name
static hasMany = [projectMemberships : ProjectMembership]
}
Project Membership
class ProjectMembership {
static constraints = {
}
static belongsTo = [user:User, project:Project]
}
Project:
class Project {
String name
static hasMany = [projectMemberships : ProjectMembership]
static constraints = {
}
}
If I have the ID of the user, how can I get a list of Project objects that they are assigned to?
There are a handful of ways - here are a couple:
def user = User.get(userId)
ProjectMembership.findAllByUser(user).collect { it.project }
or to avoid the query for the User:
ProjectMembership.withCriteria {
user {
eq('id', userId)
}
}.collect { it.project }
Be wary of queries that'll return large result sets - you'll end up with a huge in-memory list of project objects.
I'm a newbie in grails. i'm having a problem right now in my domain classes. I have 3 domain classes, class Patient,class Nurse and class NursePatient, the class NursePatient is a composite key where you can see who is the attending Nurse in a Patient, so if you view its table you can only see the id's of nurses and patients. This is my code for Nurse class:
class Nurse {
String name
Nurse partner
boolean idle = true
static belongsTo = [hospital: Hospital]
static constraints = {
name(blank:false)
partner(nullable:true)
hospital(nullable:false)
}
String toString(){
"Nurse ${name}"
}
}
--> and this is my domain class for NursePatient:
class NursePatient implements Serializable{
Nurse nurse
Patient patient
static mapping = {
version false
id composite:['nurse', 'patient']
}
static constraints = {
patient(nullable:false, validator:{val, obj -> val.hospital == obj.nurse.hospital})
nurse(nullable:false)
}
String toString(){
"Nurse ${nurse.name} - ${patient.name}"
}
void saveIt(Nurse x, Patient y){
def np = new NursePatient(nurse: x, patient: y)
if(np.save()){
def n = nurse.get(nurse.id)
n.idle = false
}
}
}
--> I was asked to print a list of nurses who doesn't have a patient. I was thinking that the moment I save in table using the saveIt() method from class NursePatient, once the save() is successful it changes the value of the property idle of class Nurse from true to false so that querying is much more easier. My problem is I don't if my code in class NursePatient is correct or is it possible to change the value of a property from another class. Please Help me.. thank You!!
Changing properties of domain classes inside different classes is fine.
However, you don't really need a NursePatient class. If you declare the relationship between Nurses and Patients as many-to-many, like this:
class Nurse {
static hasMany = [patients: Patient]
...
}
class Patient {
static hasMany = [nurses: Nurse]
...
}
then Grails will create and update the needed join table automatically. You can then query for all the nurses without patients using Criteria API:
def nursesWithoutPatients = Nurse.withCriteria { isEmpty("patients") }
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.