Grails: Children of Children - grails

I have a question about GORM and "multiple" hasmany relationships, and I didn't find an answer in my previous searches.
Let's say we have three domains:
class A {
...
static hasMany = [Bs: B]
}
and
class B {
...
static belongsTo = A
static hasMany = [Cs: C]
}
and
class C {
static belongsTo = B
String name
dateCreated date
}
I want to know if it is possible to get a list of objects of the class C, sorted by dateCreated, using an object of the class A (something like C.findAll(...., a: a.id) ) or if I have to use a more complex query ?
Best regards,

Its a little more difficult because you aren't storing a back reference to the parent objects
Something like this - I didn't test it myself
A.executeQuery("select distinct c from A a join a.bs as b join b.cs as c where a = :a", [a: a])

If B has:
static belongsTo = [a:A]
then you can do:
C.withCriteria {
a{
eq('id', <a's id here>)
}
order('dateCreated', 'desc')
}

Related

How to query 3 tables in Grails Gorm

I am new to grails framework how to query 3 tables having association between them
Class A{
static hasMany = [b:B]
}
enter code here
class B{
long aId // Id of table A
}
class c{
B b //B reference
}
SQL query: select * from C where b_id in (select id from B where a_id='10'_)
Any help will be appreciated.
Straight-forward
def list = C.withCriteria{
b{
eq 'aId', '10'
}
}

How can I get dateCreated in Has-Many Relation in Grails?

I have the following domain classes:
class A {
hasMany = [bs : B]
}
class B { }
Note that B has no backward relation to a. GORM creates a join table in my MYSQL database a_b. This table has two columns the id of a and the id of b.
How can I get a dateCreatedin the join table?
Create a model of the join table yourself and add whatever properties you want on it. Simple, and done.
For example:
class A {
static hasMany = [bs: JoinB]
}
class JoinB {
static belongsTo = [a: A]
B b
Date dateCreated
static mapping = {
autoTimestamp true // default, but I like to be explicit about it.
}
}
class B {
String whatever
}
(Careful of typos etc. I just did that off the top of my head)

Fast way to get to perform a request from multiple hasMany association

What is the fast and best way to perform a request from multiple 'hasMany' association ?
Here's a simple code that I have.
From the instance of A I want to get all instances of B domain (a list of id) where login == "toto"?
class A {
static hasMany = [BList:B]
}
class B {
static hasMany = [CList:C]
}
class C {
static hasMany = [DList:D]
}
class D {
String login
}
Thanks
You can do it with an HQL:
String query = """
from a.bList
where a = :a
and exists (select 1
from C c
, D d
where d.c = c
and c.b in a.bList
and d.login = :login)
"""
def result = A.executeQuery(query, [a: aInstance, login: "login"])
More information about executeQuery in the docs.

How to limit the Relation Elements of a Class in Grails?

I have
class User {
String name
hasMany = [books: Book]
}
class Book (
String name
belongsTo = [user: User]
}
Now, I can access all books of a user instance as:
def user = User.find("someId")
println user.books
How can I limit the number of books such that I get only the first x books from user.books?
Is there also a way to sort them?
One viable approach is to define books as List inside User. You would need to have an index column but you could get the benefit of pagination and ordering like:
class User{
List books
static hasMany = [books: Book]
}
def user = User.find("someId")
println user.books?.getAt(3..10).sort{it.name}
Note:-
All books for User will be fetched lazily, using the above approach will filter books from index 3 till 10.
In case you want to optimize the lazy fetch strategy (N + 1), then you would probably need to have a look at batchSize and order. Also sort as a side note.
Example:
class User {
String name
static hasMany = [books: Book]
static mapping = {
books batchSize: 10
}
}
class Book (
String name
static belongsTo = [user: User]
static mapping = {
order "desc"
}
}

Criteria search

I ran into some problems while trying to count items.
Imagine the following domain classes
class Book {
String name
}
class Author {
String name
static hasMany = [books:Book]
}
How do I get a list of Authors sorted by number of Books?
here's my try:
def c = Author.createCriteris()
c.list {
projections {
count 'books', 'numBooks'
groupProperty 'id'
}
order 'numBooks', 'desc'
}
but somehow I get only unusable results... and I don't know how to join the Author objects to the rsult list.... :-(
Havent tried it, but couldn't you do something like:
class Author {
String name
static hasMany = [books:Book]
static namedQueries = {
sortByMostBooks {
books {
order('size', 'desc')
}
}
}
}
And then get access by the cleaner named query
Author.sortByMostBooks.list();
In addition, you may want to include a belongsTo in you Book domain class:
static belongsTo = Author;
or:
static belongsTo = [authors:Author];
if a book is likely to have multiple authors
got something!
I still don't know how to do it with a criteria, but by switching to HQL, I succeeded.
So if someone comes up with a criteria solution, he will still get the bonus for the correct answer :-)
here is my query:
Author.executeQuery("""
select
a, size(a.books) as numBooks
from
Author a
group by
id
order by
numBooks DESC
""",[max:20])
This query isn't efficient, since it fetches all Authors in a loop, but that's ok for now.

Resources