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!!
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!!!!
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
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With