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.
Related
I have a domain class similar to the following:
class Record {
Long id
List numbers = []
String description
void recordNumber(Long number) {
//requirements, validations, etc.
numbers << number
}
}
Then I defined a Web service similar to the code below:
class RecordController extends RestfulController {
def recordNumber(Record record) {
def number = getNumberFromRequest() //request.JSON, request.XML, etc.
if (record) {
record.recordNumber(number)
record.save(flush: true, failOnError: true)
}
}
}
However, the numbers on the list don't seem to get saved, because when I retrieve a Record, the list empty. I have test for the code and it seems ok. Could it also be that the list is lazily loaded?
You are saving a new record instance each time the action is called. You should load it out of the DB instead:
def recordNumber( Long id ){
def record = Record.get id
def number = getNumberFromRequest() //request.JSON, request.XML, etc.
//....
}
So based on this answer from a previous StackOverflow question, I updated the code as follows:
class Record {
static hasMany = [numbers: Long]
Long id
String description
void recordNumber(Long number) {
//requirements, validations, etc.
addToNumbers number
}
}
It would seem that if a collection is meant to be persistent, it has to be declared this way, or be mapped in some other methods; I'm just not sure what those other methods are.
I'm introducing myself to the Grails environment (It's awesome). I've been reaping the benefits of dynamically generated methods like the findAllBy* range. However, I've come to a problem and I'm unsure about how to proceed. An hour spent on Google didn't yield all that much for me either.
Problem
I have a class like the following:
class Runner {
static hasMany = [owners: Owner]
}
And in my Owner controller, I wish to find all Runner objects, that contain a given Owner. Effectively, I'm trying to go from the many to the one.
Example
If I have an Owner object, that looks something like
Owner[name="Dave"]
And I have a Runner with something like:
Runner[owners[Owner[name="Dave"], Owner[name="James"]]]
My query should return this Runner object, but it should not return
Runner[owners[Owner[name="Bill"], Owner[name="James"]]]
My attempts
I've attempted to use the inList extension, but after some further research I realised that was designed for the other way around. My code at the moment is as follows:
def runners() {
log.info("Runners")
List<Runner> runners;
Owner owner;
if (params.id) {
log.info("Id = " + params.id);
owner = Owner.get(params.id);
log.info("owner = " + owner.name);
// Grab runners in list thing.
log.info("Number of results = " + runners.size());
}
[results: results, jockeyInstance: jockey]
}
After some research into HQL, I found a more elegant solution that didn't require me to change the Domain classes at all. The query I used was as follows:
runners = Runner.executeQuery("FROM Runner as r WHERE :owner in elements(r.owners)", [owner : ownerInstance]);
Where ownerInstance is the Owner object being used to map to the Runner.
maybe not the answer for the question at hand, but you could also make the runners known to the owners like this
class Runner {
String name
static hasMany = [ owners: Owner ]
static belongsTo = Owner
}
class Owner {
String name
static hasMany = [ runners: Runner ]
}
Owner o1 = new Owner(name: "O1").save()
Owner o2 = new Owner(name: "O2").save()
Owner o3 = new Owner(name: "O3").save()
new Runner(name: "R1").with{
addToOwners(o1)
addToOwners(o2)
save()
}
new Runner(name: "R2").with{
addToOwners(o1)
addToOwners(o3)
save()
}
print o3.runners
results in [runnerowner.Runner : 2]
Is this something you are expecting?
def results = Runner.withCriteria {
owners {
eq 'name', 'Dave'
//idEq params.id //If id of owner is provided
}
}
assuming you have
class Runner {
static hasMany = [owners: Owner]
}
class Owner {
String name
}
Here is a sample you can try.
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 am trying to get a pagedResultList using chained named queries, but i seem to fail.
Any hints or tips on how this can be achieved?
See modified example below from the Grails documentation that should illustrate my needs
def books = Publication.recentPublications.grailsInTitle.list(params) {
or {
like 'author', 'Tony%'
like 'author', 'Phil%'
}
}
This always returns an ArrayList..
When or remove the additional criteria and use it like below it works
def books = Publication.recentPublications.grailsInTitle.list(params)
I would like to add some criteria closures, any hints or tips on how i could achieve this?
I am facing same problems with named queries. This is my solution applied to your classes. Comment if it works for you.
class Publication {
//fields, constraints, etc.
namedQueries = {
authoredLike { String authorName ->
if (authorName) {
like 'author', authorName
}
// untested, but you get the point, please experiment
authoredLikeMany { List<String> authors ->
authors.each { String authorName -> like 'author', authorName }
}
}
}
def tonyBooks = Publication.recentPublications.grailsInTitle.authoredLike('Tony%').list(params)
def tonyAndPhilBooks = Publication.recentPublications.grailsInTitle.authoredLikeMany(['Tony%', 'Phil%']).list(params)
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.