简介
TypeORM是一个ORM(对象关系映射器)框架,它允许开发人员使用面向对象的方式来管理关系型数据库。借助TypeORM,可以轻松地创建、更新和查询数据库表。它为Node.js应用开发者提供了一个大量的有用的特性,包括实体(数据库表)、关系、查询和事务。
一、TypeORM多对多
1、通过@JoinTable装饰器实现实体间多对多关系
@Entity() class User { @PrimaryGeneratedColumn() id: number; @ManyToMany(() => Role) roles: Role[]; } @Entity() class Role { @PrimaryGeneratedColumn() id: number; @ManyToMany(() => User, user => user.roles) @JoinTable() users: User[]; }
上述例子展示如何在TypeORM中实现基于关系的实体间多对多关系。通过 @JoinTable() 装饰器来指定关系表的名称和两个实体的关系列。
2、复杂的多对多关系
在某些情况下,多对多关系可能非常复杂。TypeORM可以通过在中间表上使用额外的列来解决这种问题。比如下面的代码展示了如何为用户和角色之间的关系添加有效期和说明:
@Entity() class User { @PrimaryGeneratedColumn() id: number; @ManyToMany(() => Role, role => role.users, { cascade: true, onDelete: 'CASCADE', }) @JoinTable({ name: 'user_role', joinColumn: { name: 'user_id', referencedColumnName: 'id', }, inverseJoinColumn: { name: 'role_id', referencedColumnName: 'id', }, }) roles: Role[]; } @Entity() class Role { @PrimaryGeneratedColumn() id: number; @ManyToMany(() => User, user => user.roles, { cascade: true, onDelete: 'CASCADE', }) @JoinTable({ name: 'user_role', joinColumn: { name: 'role_id', referencedColumnName: 'id', }, inverseJoinColumn: { name: 'user_id', referencedColumnName: 'id', }, }) users: User[]; @OneToMany(() => UserRole, userRole => userRole.role, { cascade: true }) userRoles: UserRole[]; } @Entity() class UserRole { @PrimaryGeneratedColumn() id: number; @Column() validFromDate: Date; @Column() validToDate: Date; @Column({ nullable: true }) description: string; @ManyToOne(() => User, user => user.userRoles, { onDelete: 'CASCADE' }) @JoinColumn({ name: 'user_id' }) user: User; @ManyToOne(() => Role, role => role.userRoles, { onDelete: 'CASCADE' }) @JoinColumn({ name: 'role_id' }) role: Role; }
上述代码表示了三个实体:User、Role和UserRole,其中UserRole是一个中间表实体,它有一个ManyToOne关系与User和Role实体相关联。UserRole实体包含了validFromDate、validToDate和description等字段。这些字段被用来记录用户和角色之间关系的相关信息。
二、TypeORM type选项
TypeORM是一款强大的ORM框架,用户可以使用type选项来指定字段类型。这个特性非常实用,因为它可以帮助开发人员正确地映射数据库表字段到实体字段。
1、type选项
type选项可以为被装饰器装饰的字段指定一个JavaScript类型和一个数据库类型。例如,下面的代码展示了如何为一个实体定义一个varchar类型的实体字段:
@Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column({ type: 'varchar', length: 100, }) name: string; }
在上面的示例中,name字段被映射到一个名为“name”的varchar(100)类型的数据库列。TypeORM默认使用列的名称来映射字段,因此在这个示例中,name字段被映射到一个名为“name”的数据库列。
2、Decimal类型
TypeORM为处理数据库中的货币值提供了两种默认的DECIMAL类型:DECIMAL(19,2)和DECIMAL(10,0)。DECIMAL(19,2)用于处理带有两位小数的货币值,而DECIMAL(10,0)用于处理整数货币值。
@Entity() export class Product { @PrimaryGeneratedColumn() id: number; @Column({ type: 'decimal', precision: 19, scale: 2, }) price: number; }
在上面的代码中,price字段被映射到一个名为“price”的DECIMAL(19,2)列。precision选项指定了列的总位数,而scale选项指定了小数点后面的位数。
3、Enum类型
枚举类型对于组织代码非常有用。TypeORM允许开发人员将一个JavaScript枚举对象映射到一个数据库表列,从而方便地使用枚举类型。
enum BookStatus { ACTIVE = 'Active', PENDING = 'Pending', DELETED = 'Deleted', } @Entity() export class Book { @PrimaryGeneratedColumn() id: number; @Column({ type: 'enum', enum: BookStatus, default: BookStatus.PENDING, }) status: BookStatus; }
在上面的代码中,BookStatus枚举被映射到一个名为“status”的列。使用enum选项来指定枚举类型,在default选项中指定默认枚举值。
三、TypeORM事务
事务是指一组相关的数据库操作,执行这些操作时必须遵循ACID特性,即原子性、一致性、隔离性和持久性。在TypeORM中,使用Repository对象的事务功能可以简单地实现这些操作。
async function createCustomerAndOrder() { const connection = getConnection(); const queryRunner = connection.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const customer = new Customer(); customer.firstName = 'John'; customer.lastName = 'Doe'; const order = new Order(); order.title = 'Order 1'; await queryRunner.manager.save(customer); await queryRunner.manager.save(order); await queryRunner.commitTransaction(); } catch (err) { await queryRunner.rollbackTransaction(); throw err; } finally { await queryRunner.release(); } }
在上面的代码中,我们使用getConnection()和createQueryRunner()方法来获取连接和查询运行器。接下来,通过调用createQueryRunner().startTransaction()方法来开始一个事务。在 try 块中,创建和保存Customer和Order实体对象。最后,调用createQueryRunner().commitTransaction()完成事务操作。
结论
总之,TypeORM是一个强大的ORM框架,它具有许多特性,包括实体(数据库表)、关系、查询和事务。多对多关系、type选项和事务是TypeORM中特别有用的特性,能够使你更加便捷地实现你的应用程序。因此,TypeORM是开发高质量Node.js应用程序的不二之选。