Association Loading Without N+1 Queries
Evidence status: API-shape review only. The illustrative relation methods have not been executed in the current generated Java baseline, and no retained SQL/query-count result proves the N+1 outcome yet.
Problem
Load the relations required by a page without issuing one application query per parent row or loading an unrestricted object graph.
Java Path
Express the relation shape in the generated request:
Q.orders()
.selectUser(Q.usersWithIdField().selectName())
.selectLineItemList(
Q.lineItemsWithId()
.selectSkuName()
.limit(3)
)
.comment("Query orders with summary relations")
.purpose("Render the order list")
.executeForList(ctx);
The relation and selector names are illustrative. Use the exact methods emitted for the model.
Choose the smallest relation operation that answers the page:
- scalar selectors for list labels;
- nested selectors for detail views;
- child
limitfor previews; - generated child counts for badges;
have/haveNohelpers for existence conditions.
Verification
- Enable SQL/query diagnostics appropriate to the runtime.
- Load several parents with several children each.
- Confirm query count does not grow linearly with the number of parents.
- Confirm only selected child fields and intended relations are returned.
- Confirm nested tenant and permission boundaries.
- Test parents with zero, one, and many children.
Failure Modes
| Symptom | Fix |
|---|---|
| One child query per parent | Move relation loading into the generated selection request. |
| Response graph is too large | Select fewer fields, limit preview children, or split list/detail paths. |
| Child scope leaks | Apply and test nested request policy and model ownership. |
| Method is missing | Inspect generated relation/request source; do not guess or patch output. |