pub struct EagerLoader { /* private fields */ }Expand description
Eager Loading 执行器
自动执行主表 + 关联表查询并组装结果,消除 N+1 查询。
Implementations§
Source§impl EagerLoader
impl EagerLoader
Sourcepub fn new(relation: RelationDef) -> Self
pub fn new(relation: RelationDef) -> Self
创建 EagerLoader
Sourcepub fn with(self, relation: RelationDef) -> Self
pub fn with(self, relation: RelationDef) -> Self
添加子级关联(v2.2.0 扩展为无限级链式调用)
每次 with() 追加到最深层级,构建线性关联链:
ⓘ
EagerLoader::new(order_relation) // User → Order
.with(order_item_relation) // Order → OrderItem
.with(product_relation) // OrderItem → Product
// 构建 4 级链:User → Order → OrderItem → ProductSourcepub fn with_cycle_policy(self, policy: CyclePolicy) -> Self
pub fn with_cycle_policy(self, policy: CyclePolicy) -> Self
设置循环检测策略(v2.2.0 新增)
ⓘ
use sz_orm_core::cycle_detection::CyclePolicy;
let loader = EagerLoader::new(rel)
.with(child_rel)
.with_cycle_policy(CyclePolicy::Truncate);Sourcepub fn smart(self) -> SmartEagerLoader
pub fn smart(self) -> SmartEagerLoader
切换到智能策略选择模式(v2.3.0 新增)
返回 SmartEagerLoader,
基于 RelationKind 自动选择最优加载策略:
- HasOne / BelongsTo → JOIN(单次查询)
- HasMany → Data Loader(批量 IN 查询)
- ManyToMany → 中间表批量查询
原有 EagerLoader API(new/with/load_many/load_nested)不变,
此方法为扩展入口,不影响 v2.2.0 代码行为。
ⓘ
use sz_orm_core::eager_loader::EagerLoader;
let loader = EagerLoader::new(order_rel)
.with(item_rel)
.smart();
let tree = loader.load(&mut conn, "SELECT id, name FROM users").await?;Sourcepub fn children_count(&self) -> usize
pub fn children_count(&self) -> usize
返回子级关联链深度(v2.2.0 改为递归计算)
Sourcepub fn child_names(&self) -> Vec<&str>
pub fn child_names(&self) -> Vec<&str>
返回子级关联名称列表(v2.2.0 改为递归遍历链)
Sourcepub async fn load_many(
&self,
conn: &mut dyn Connection,
main_sql: &str,
) -> Result<Vec<EagerResult>, DbError>
pub async fn load_many( &self, conn: &mut dyn Connection, main_sql: &str, ) -> Result<Vec<EagerResult>, DbError>
执行 HasMany 双查询策略
- 执行主表 SQL → 提取主键列表
- 生成
WHERE fk IN (?, ...)批量查询 - 执行关联表查询 → 按外键分组组装
- 若有 children,递归加载子级关联(限 2 级)
Sourcepub async fn load_nested(
&self,
conn: &mut dyn Connection,
main_sql: &str,
) -> Result<Vec<NestedEagerResult>, DbError>
pub async fn load_nested( &self, conn: &mut dyn Connection, main_sql: &str, ) -> Result<Vec<NestedEagerResult>, DbError>
执行多级 Eager Loading,返回嵌套结果树(v2.2.0 新增)
自动执行主表 + 各级关联表批量查询,组装 Vec<NestedEagerResult> 嵌套树。
每级使用 WHERE fk IN (?, ...) 参数化批量查询,消除 N+1。
循环检测根据 cycle_policy 策略处理循环引用。
§执行流程
- 初始化
CycleDetector(cycle_policy) - 执行主表 SQL 获取根行
- 递归加载各子级:提取父级主键 →
WHERE fk IN (?, ...)批量查询 → 按外键分组 → 递归子级 - 返回
NestedEagerResult嵌套树
§参数
conn:数据库连接main_sql:主表查询 SQL
§异常处理
- 结果集超内存限制(>1,000,000 行)→
Err(DbError::InvalidInput)含建议改用 Stream API - 循环检测策略为
Error且检测到循环 →Err(DbError::InvalidInput)含循环路径
ⓘ
let loader = EagerLoader::new(order_rel)
.with(item_rel)
.with(product_rel)
.with_cycle_policy(CyclePolicy::Truncate);
let tree = loader.load_nested(&mut conn, "SELECT id, name FROM users").await?;
// tree: Vec<NestedEagerResult>(4 级嵌套树)Auto Trait Implementations§
impl Freeze for EagerLoader
impl RefUnwindSafe for EagerLoader
impl Send for EagerLoader
impl Sync for EagerLoader
impl Unpin for EagerLoader
impl UnsafeUnpin for EagerLoader
impl UnwindSafe for EagerLoader
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more