请问typeORM 的多表查询中`leftJoinAndSelect`和`leftJoinAndMapMany`的区别是什么呢?

请问:
typeORM 的多表查询中 leftJoinAndSelect 的作用是什么呢?

我问AI但是没有理解意思:

现在,我们想要查询所有用户以及他们关联的订单信息,就可以使用 leftJoinAndSelect 来实现,示例代码如下:


import { getRepository } from 'typeorm';
import { User } from './User';

async function queryUsersWithOrders() {
    const userRepository = getRepository(User);
    const users = await userRepository
       .createQueryBuilder('user')
       .leftJoinAndSelect('user.orders', 'order')
       .getMany();

    return users;
}

// 调用查询函数
queryUsersWithOrders().then((users) => {
    console.log(users);
});

查询结果:

[
    {
        "id": 1,
        "name": "Alice",
        "email": "alice@example.com",
        "orders": [
            {
                "id": 101,
                "orderNumber": "20241227001",
                "totalAmount": 100.00,
                "user": {
                    "id": 1,
                    "name": "Alice",
                    "email": "alice@example.com"
                }
            },
            {
                "id": 102,
                "orderNumber": "20241227002",
                "totalAmount": 150.00,
                "user": {
                    "id": 1,
                    "name": "Alice",
                    "email": "alice@example.com"
                }
            }
        ]
    },
    {
        "id": 2,
        "name": "Bob",
        "email": "bob@example.com",
        "orders": [
            {
                "id": 103,
                "orderNumber": "20241227003",
                "totalAmount": 200.00,
                "user": {
                    "id": 2,
                    "name": "Bob",
                    "email": "bob@example.com"
                }
            }
        ]
    }
]

不知道leftJoinAndSelectleftJoinAndMapMany的区别是什么。

阅读 638
3 个回答

leftJoinAndSelect:自动选择并包含关联表的数据,使用实体中预定义的属性名,适用于直接访问关联数据的情况。

leftJoinAndMapMany:手动映射关联表的数据,允许自定义属性名,适用于需要自定义结果结构的情况。

例子

// User.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
import { Order } from './Order';

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @Column()
    email: string;

    @OneToMany(() => Order, order => order.user)
    orders: Order[]; // 这里定义了 orders 属性
}

// Order.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { User } from './User';

@Entity()
export class Order {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    orderNumber: string;

    @Column()
    totalAmount: number;

    @ManyToOne(() => User, user => user.orders)
    user: User;
}

使用 leftJoinAndSelect

当你使用 leftJoinAndSelect 时,TypeORM 会自动将 Order 实体的数据映射到 User 实体的 orders 属性中。

import { getRepository } from 'typeorm';
import { User } from './User';

async function queryUsersWithOrders() {
    const userRepository = getRepository(User);
    const users = await userRepository
       .createQueryBuilder('user')
       .leftJoinAndSelect('user.orders', 'order') // 这里使用了 orders 属性
       .getMany();

    return users;
}

// 调用查询函数
queryUsersWithOrders().then((users) => {
    console.log(users);
});

结果

[
    {
        "id": 1,
        "name": "Alice",
        "email": "alice@example.com",
        "orders": [
            {
                "id": 101,
                "orderNumber": "20241227001",
                "totalAmount": 100.00
            },
            {
                "id": 102,
                "orderNumber": "20241227002",
                "totalAmount": 150.00
            }
        ]
    },
    {
        "id": 2,
        "name": "Bob",
        "email": "bob@example.com",
        "orders": [
            {
                "id": 103,
                "orderNumber": "20241227003",
                "totalAmount": 200.00
            }
        ]
    }
]

使用 leftJoinAndMapMany

当你使用 leftJoinAndMapMany 时,你可以自定义属性名,例如 userOrders,而不是使用实体中预定义的 orders 属性。

import { getRepository } from 'typeorm';
import { User } from './User';

async function queryUsersWithOrders() {
    const userRepository = getRepository(User);
    const users = await userRepository
       .createQueryBuilder('user')
       .leftJoinAndMapMany('user.userOrders', 'user.orders', 'order') // 这里自定义了 userOrders 属性
       .getMany();

    return users;
}

// 调用查询函数
queryUsersWithOrders().then((users) => {
    console.log(users);
});

结果

[
    {
        "id": 1,
        "name": "Alice",
        "email": "alice@example.com",
        "userOrders": [
            {
                "id": 101,
                "orderNumber": "20241227001",
                "totalAmount": 100.00
            },
            {
                "id": 102,
                "orderNumber": "20241227002",
                "totalAmount": 150.00
            }
        ]
    },
    {
        "id": 2,
        "name": "Bob",
        "email": "bob@example.com",
        "userOrders": [
            {
                "id": 103,
                "orderNumber": "20241227003",
                "totalAmount": 200.00
            }
        ]
    }
]

补充

选择依据:

  • 如果关系已在实体中定义,优先使用 leftJoinAndSelect。
  • 如果需要灵活映射数据到自定义字段,使用 leftJoinAndMapMany。

区别总结

特性leftJoinAndSelectleftJoinAndMapMany
用途加载实体之间已有关系的数据加载数据并映射到自定义属性
依赖实体关系定义是,基于实体定义的 @OneToMany、@ManyToOne 等关系否,可以映射到自定义的字段
适用场景加载与主实体有关联的实体数据映射额外的自定义字段或未定义关系的实体数据
映射目标实体中已定义的关联属性实体中自定义的属性,未必在实体定义中存在
示例加载用户的 orders 属性映射用户的订单到 userOrders 属性(可能未定义)

leftJoinAndSelect和leftJoinAndMapMany的区别

我的理解就是没啥区别,但是实际有区别我还不熟

特点leftJoinAndSelectleftJoinAndMapMany
功能用于进行左连接,并将关联的实体对象一并选择返回。用于进行左连接,但通过映射返回与连接的实体对象不同的数据。
返回值返回的是完整的关联实体对象,包含所有的列数据。返回的是根据映射函数定义的数据,通常用于定制 化返回结果。
使用场景常用于查询并且需要返回完整的关联实体数据。常用于查询并且需要返回定制化的数据,而不是关联实体的完整数据。
常见应用leftJoinAndSelect('user.orders' ,'order')leftJoinAndMapMany('user.orders','order','order.alias')
返回的对象类型返回的是关联表的实体对象,类型和关联表一致返回的是通过映射处理后的对象,类型可以根据映射函数自定义。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏