# 关联预取与批加载

视图里一行 `.with`，框架自动决定怎么取关联数据。理解背后的两种 SQL 策略，才能写好高性能查询。

## m2o：双语句批加载

嵌套 `c.store.with(...)`（n+1 场景）默认**不 join**，而是两条语句：

```ts workspace
// ① 模型（完整可运行版见工作区）
import { model, prop, dto } from '@ts-grm/core'
import { sqlClient } from './infra/sql-client'

const BookStore = model("BookStore", "id", class {
    id = prop.i64()
    name = prop.str(100)
})

const Book = model("Book", "id", class {
    id = prop.i64()
    name = prop.str(50)
    edition = prop.i32()
    price = prop.num(10, 2)
    store = prop.m2o(BookStore).nullable()
})

const BookView = dto.view(Book, c => [
    c.$allScalars,
    c.store.with(c => [c.id, c.name]),
])

const rows = await sqlClient.createQuery(Book, (q, book) => {
    return q.select(book.fetch(BookView))
}).fetchList()

console.log(rows.map(r => `${r.name} @ ${r.store?.name}`).join('\n'))
```

跑完看结果面板的 **SQL 追踪**，是两段：

```sql
select ... from BOOK tb_1_                              -- 主查询
select ID, NAME from BOOK_STORE tb_1_ where ID in(?, ?) -- 加载关联：按主查询收集的去重 id 批量取
```

- **第二段的 IN 列表 = 主查询结果里收集的去重 store_id**——恒为"两段"，不随结果行数膨胀成 N 条（天然防 N+1）；
- 关联条数不多时，这种方式比 JOIN 更省（避免行数膨胀与列重复）。

## o2m / m2m：key 匹配后展开

集合方向（`books`、`authors`）同理：先查主表，再按**主表主键 IN** 把关联集合按 source 分组回填成数组。SQL 追踪同样能看到第二段形如 `select ... from BOOK where STORE_ID in(?, ?)`。

## 何时会 join：fetchOptions

偏移/分页很大、或需要按关联列排序/过滤时，批加载不一定会退化成 JOIN。相关控制：

| 选项 | 作用 |
|---|---|
| `maxJoinFetchDepth` | join 取形的最大嵌套深度（默认 5，超限报错而非静默折衷） |
| `maxJoinFetchOffset` | 关联批加载退化为 join 的偏移阈值 |
| `defaultBatchSize` / `defaultListBatchSize` | 主/集合方向的批加载 IN 上限（默认 128 / 16） |

它们都是 `newSqlClient(driver, options)` 的构建选项（[「SQL 后端」](../sql-backend/driver)章展开）。

## 关联顺序

集合方向可声明默认排序（`prop.o2m(...).orderBy(...)`），取形时自动带上；查询内也能 `q.orderBy(book.store.name)` 之类的关联列排序（会触发对应取形策略）。

## 内功心法

- **恒两段**、按 key 批加载是 ts-grm 的默认取形路线——界面列多、行多时最省；
- 需要 join 语义（关联列过滤/排序、行数精确）时用条件/排序驱动，或者干脆把关联列展开成普通列查询；
- 复杂批加载与 join 的实测量化，可在你自己的库里开 SQL 追踪对比（见「SQL 日志与追踪」）。

## 本章小结

查询 API 十页收束：根查询 → 条件 → 排序 → 取形 → 分页 → 聚合 → 子查询 → CTE → 原生 SQL → 关联预取。下一章进入 **SQL 后端**：驱动、事务、方言与命名策略。
