Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Major
-
Resolution: Won't Fix
-
Affects Version/s: 1.3.3
-
Fix Version/s: None
-
Component/s: None
-
Labels:None
Description
If I have the following domain model:
class Author {
String name
static hasOne = [ location: Location ]
}
class Location {
String city
}
then when I execute this code:
Author.list().each { a ->
println a.location.city
}
I find that the location instances are all loaded up front with separate SELECTs. In other words, they're loaded eagerly. Explicitly specifying the relationship as lazy: true has no effect.
Perhaps this behaviour is expected, but it seems strange to me.
-
Hide
- hasone-example.zip
- 28/Jul/10 3:12 AM
- 182 kB
- Peter Ledbrook
-
- hasone-example/.classpath 0.7 kB
- hasone-example/.project 0.5 kB
- hasone-example/.../org.codehaus.groovy.eclipse.preferences.prefs 0.1 kB
- hasone-example/application.properties 0.2 kB
- hasone-example/.../.DataSource.groovy.swp 12 kB
- hasone-example/.../BootStrap.groovy 0.5 kB
- hasone-example/.../BuildConfig.groovy 1 kB
- hasone-example/grails-app/.../Config.groovy 3 kB
- hasone-example/.../DataSource.groovy 0.8 kB
- hasone-example/.../resources.groovy 0.0 kB
- hasone-example/.../UrlMappings.groovy 0.2 kB
- hasone-example/grails-app/.../Author.groovy 0.2 kB
- hasone-example/.../Location.groovy 0.2 kB
- hasone-example/.../messages.properties 3 kB
- hasone-example/.../messages_da.properties 3 kB
- hasone-example/.../messages_de.properties 4 kB
- hasone-example/.../messages_es.properties 3 kB
- hasone-example/.../messages_fr.properties 2 kB
- hasone-example/.../messages_it.properties 2 kB
- hasone-example/.../messages_ja.properties 2 kB
- hasone-example/.../messages_nl.properties 3 kB
- hasone-example/.../messages_pt_BR.properties 3 kB
- hasone-example/.../messages_pt_PT.properties 3 kB
- hasone-example/.../messages_ru.properties 4 kB
- hasone-example/.../messages_th.properties 5 kB
- hasone-example/.../messages_zh_CN.properties 2 kB
- hasone-example/grails-app/.../error.gsp 2 kB
- hasone-example/grails-app/.../index.gsp 4 kB
- hasone-example/grails-app/.../main.gsp 0.7 kB
- hasone-example/web-app/css/main.css 5 kB
Issue Links
- duplicates
-
GRAILS-5077
hasOne mapping is by default eager and cannot be changed to lazy
-
- is related to
-
GRAILS-6538
Bidirectional 'one-to-one' mapping results in extra unnecessary query on relationship
-
Activity
- All
- Comments
- Work Log
- History
- Activity
- Git Commits
I have stepped into this a bit and I see that the fetch mode on the corresponding DefaultGrailsDomainClassProperty object is GrailsDomainClassProperty.FETCH_LAZY (0). I am still trying to figure out why the relationship is being eagerly fetched.
I have found that even if I use the Hibernate API directly to retrieve an Author, its Location is eagerly fetched. That tells me that the eager fetching is not being triggered by GORM query code.
To add to the confusion, GRAILS-6538 suggests that hasOne results in no extra query.
OK, ignore that. GRAILS-6538 is talking about an extra query to fetch the Author from the associated location. Different (albeit related) issue.
http://community.jboss.org/wiki/AShortPrimerOnFetchingStrategies
(The exception is a one-to-one association with a shared primary key: a proxy for the target of an association can only be used if the target is required. If a Person has a one-to-one association to a Desk entity, the primary key value of the Desk must be the same as the primary key value of the Person. The Desk can only be proxied if the Person primary key column has a foreign key constraint referencing the primary key column of Desk, making it non-optional and required; a Person needs a Desk. If this foreign key constraint is not present, or if the foreign key constraint is not mapped in Hibernate with constrained="true" in XML or optional="false" in annotations, no proxy for a Desk can be used, and Hibernate has to hit the database, either with a join or a secondary immediate query, to find out if the association is really null or not. You can use bytecode injected interception to get lazy loading in that case. Read this page for an alternative explanation of the same issue.)
So there are some one-to-one mappings in which the association will always be eagerly fetched. Perhaps the issue is that the foreign key constraint is not mapped correctly? Or the 'constrained' is not true?
Attaching an example project. Run the Grails console and then execute
new BootStrap().init()followed by
Author.list().each { a -> println a.name }Even though the above code doesn't use the location at all, you'll see in the console output that the locations for each author are loaded up front.