Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way in Grails to eager fetch the whole record?

I am trying to find if there is any way in Grails to eager fetch complete records instead of a left Join.

I have two classes with one to many mapping. When I try to get all the records and render as XML, only the IDs of the "many" side get into the XML file. Is there anyway to get the whole records?

The example that I am using is as following:

I have 3 classes:

User, Book and Chapter

Users and Book have a many to many mapping and Book to Chapters is a one to many mapping. I have a class UserBook which defines the many to many relationship. Now I have the following code

user = User.findByUserId(params.userid.toString())
        def books = user.getAllBooks()
        render books as XML

Set<Book>getAllBooks() {
        UserBook.findAllByUser(this).collect {it.book} as Set
    }

The above renders an XML with the books and also the chapter IDs for each book. What I wanted was the "books" above to contain all the chapter information as well.

Thanks!!

like image 615
iKT Avatar asked Dec 27 '11 11:12

iKT


3 Answers

The docs says:

The default fetch strategy used by Grails is "lazy", which means that the collection will be lazily initialized. This can lead to the n+1 problem if you are not careful. If you need "eager" fetching you can use the ORM DSL or specify eager fetching as part of a query

You can specify the fetch strategy in the domain class, but IMHO, the best strategy to obtain a 1-m relationship is with fetch or join in the query through methods added to Domain Class or Criteria, for example:

// You have a Book with many Authors, then you specify the fetching strategy with eager
def results = Book.list(fetch:[authors:"eager"])

In other case you can use criteria with Hibernate Fetch Mode:

import org.hibernate.FetchMode as FM
…
def results = c.list {
    maxResults(10)
    firstResult(50)
    fetchMode("aRelationship", FM.JOIN)
}

Or better if you know HQL, then you can use it, because is possible to indicate fetching in HQL, for example: def result = DomainClass.findAll("HQL_Sentence")

Cool uh!!!!

like image 180
neodevelop Avatar answered Nov 16 '22 01:11

neodevelop


If you're looking for the XML output to contain the full chapter information instead of the ID only, try using the 'deep' XML marshalling (works the same for JSON, too):

XML.use('deep') {
    render books as XML
}
like image 41
Clemens Sum Avatar answered Nov 16 '22 01:11

Clemens Sum


Check out the docs section 5.3.4. It's done using the fetchMode in you domain class:

static fetchMode = [things:"eager"]

However, if your looking for just the ID's of an object to fill an XML file (or another field) I would check out the projection criteria for better performance on large collections.

like image 2
Michael J. Lee Avatar answered Nov 16 '22 01:11

Michael J. Lee