Every 'hasOne' Relationship is eagerly fetched by default and cannot be configured as lazy: true
- Dominant language
- Groovy
- Stars
- 2.9k
- Forks
- 975
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 92
Description
Consider two domain entities:
```
@Entity
class AParent {
// ...
static hasOne = [child:AChild]
// ...
}
```
```
@Entity
class AChild {
// ...
static belongsTo = [parent:AParent]
// ...
}
```
If I have a list of 10 ids for Entity 'AParent' and make the following call:
`AParent.findAllByIdInList( aIds )`
This single call (without _ever_ attempting to programmatically access 'child') immediately triggers 10 additional hibernate sql selects to get each individual child (where each AParent hasOne AChild).
And so one 'findAllByIdInList' call triggers 11 db calls, with no explicit requests of the child entity and explicit lazy configuration:
Additionally, there is no way to disable this eager fetching. The following static mappings fail to have the desired impact:
- child fetch: 'select'
- child fetch: 'lazy'
- child lazy: 'true'
Example output from the 1 call `AParent.findAllByIdInList( aIds ) // with 10 ids`
```Hibernate: select this_.id as id1_1_0_, this_.version as version2_1_0_, this_.parent_description as parent_d3_1_0_ from a_parent this_ where this_.id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
Hibernate: select achild0_.id as id1_0_0_, achild0_.version as version2_0_0_, achild0_.description as descript3_0_0_, achild0_.parent_id as parent_i4_0_0_ from a_child achild0_ where achild0_.parent_id=?
```
The main issue is that this relationship *cannot* be configured as lazy (at least not any way that I am aware of, and traditional static mappings do not work).
Less importantly, it could be argued that the default for the hasOne _should_ be lazy (like the hasMany), but this is not the case.
This can be easily reproduced with the following Micronaut 1.1.1 + GORM 7.0.0 Repository:
https://github.com/alanbino/gorm-hasone
Contributor guide
Research direction
Start with the AParent and AChild mappings and the AParent.findAllByIdInList(aIds) call described in the issue, then reproduce the behavior using the linked Micronaut 1.1.1 and GORM 7.0.0 repository. Compare the generated SQL with the configured fetch and lazy options; done means hasOne can be configured without issuing child selects when the relationship is not accessed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- groovy
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100