预加载关联 (Eager Loading)
预加载是一种在查询主实体时同时加载其关联数据的技术。IBest ORM 提供了强大的预加载功能,支持嵌套关联和复杂查询场景。
基础用法
使用 with() 方法
typescript
// 预加载单个关联
const user = orm.query(User)
.with('profile')
.first();
// 预加载多个关联
const users = orm.query(User)
.with('profile')
.with('orders')
.with('roles')
.find();详细用法指南
查询方法
typescript
// first() - 查询单条记录及关联
const user = orm.query(User)
.with('profile')
.where({ id: 1 })
.first();
// find() - 查询多条记录及关联
const users = orm.query(User)
.with('profile')
.with('articles')
.find();复杂嵌套示例
typescript
// 查询用户的完整信息:档案、文章、用户角色
const user = orm.query(User)
.with('profile')
.with('articles')
.with('roles')
.where({ id: 1 })
.first();
console.log('完整用户数据:', user);
// 输出:
// {
// id: 1,
// name: "张三",
// email: "zhangsan@example.com",
// profile: {
// id: 1,
// userId: 1,
// avatar: "avatar1.jpg",
// bio: "热爱技术的程序员"
// },
// articles: [
// {
// id: 1,
// title: "TypeScript入门指南",
// content: "TypeScript是JavaScript的超集...",
// authorId: 1
// }
// ],
// roles: [
// {
// id: 1,
// name: "admin",
// description: "管理员"
// }
// ]
// }不同关联类型的预加载
Has One 关联预加载
typescript
// 用户档案(一对一)
const user = orm.query(User)
.with('profile')
.where({ id: 1 })
.first();
// 结果中 profile 是单个对象或 undefined
console.log('用户档案:', user?.profile);Has Many 关联预加载
typescript
// 用户文章(一对多)
const user = orm.query(User)
.with('articles')
.where({ id: 1 })
.first();
// 结果中 articles 是数组
console.log('文章数量:', user?.articles?.length || 0);Belongs To 关联预加载
typescript
// 文章作者(多对一)
const article = orm.query(Article)
.with('author')
.where({ id: 1 })
.first();
// 结果中 author 是单个对象或 undefined
console.log('文章作者:', article?.author?.name);Many To Many 关联预加载
typescript
// 用户角色(多对多)
const user = orm.query(User)
.with('roles')
.where({ id: 1 })
.first();
// 结果中 roles 是数组
console.log('角色列表:', user?.roles?.map(role => role.name));批量预加载
typescript
// 查询所有用户及其档案和文章
const users = orm.query(User)
.with('profile')
.with('articles')
.find();
users.forEach(user => {
console.log(`用户: ${user.name}`);
console.log(`档案: ${user.profile?.bio || '无'}`);
console.log(`文章数: ${user.articles?.length || 0}`);
console.log('---');
});
// 分页查询与预加载
const usersPage = orm.query(User)
.with('profile')
.with('articles')
.limit(10)
.offset(0)
.find();条件查询与预加载
typescript
// 查询活跃用户及其文章
const activeUsers = orm.query(User)
.with('articles')
.where({ status: 'active' })
.find();
// 多条件查询
const filteredUsers = orm.query(User)
.with('profile')
.with('articles')
.where({ status: 'active' })
.where({ age: { gte: 18 } })
.find();性能优化
选择性预加载
只预加载需要的关联,避免不必要的数据传输:
typescript
// 好的做法:只预加载需要的关联
const users = orm.query(User)
.with('profile') // 只预加载用户资料
.find();
// 避免:预加载所有关联
const users = orm.query(User)
.with('profile')
.with('orders')
.with('roles')
.with('permissions')
.with('settings')
.find();实际应用示例
用户详情页面
typescript
function getUserDetails(userId: number) {
const user = orm.query(User)
.with('profile')
.with('orders')
.with('roles')
.where({ id: userId })
.first();
return {
user: {
id: user?.id,
name: user?.name,
email: user?.email,
bio: user?.profile?.bio,
avatar: user?.profile?.avatar
},
orders: user?.orders?.map(order => ({
id: order.id,
productName: order.productName,
amount: order.amount
})) || [],
roles: user?.roles?.map(role => role.name) || []
};
}订单列表页面
typescript
function getOrdersList(page: number = 1, limit: number = 20) {
const orders = orm.query(Order)
.with('user')
.orderBy('createdAt', 'desc')
.offset((page - 1) * limit)
.limit(limit)
.find();
return orders.map(order => ({
id: order.id,
productName: order.productName,
amount: order.amount,
userName: order.user?.name
}));
}仪表板统计
typescript
function getDashboardStats() {
const users = orm.query(User)
.with('orders')
.with('roles')
.find();
return {
totalUsers: users.length,
totalOrders: users.reduce((sum, user) => sum + (user.orders?.length || 0), 0),
adminUsers: users.filter(user =>
user.roles?.some(role => role.name === 'admin')
).length
};
}常见问题
Q: 预加载的关联为空数组或 undefined?
A: 检查以下几点:
- 关联配置是否正确(外键、目标类等)
- 数据库中是否存在关联数据
- 外键值是否正确
Q: 预加载性能较差?
A: 优化建议:
- 只预加载必需的关联
- 使用分页限制结果集大小
- 避免预加载过多关联