跳转到主要内容

ActiveRecord 与 DataMapper

什么是 Active Record 模式?

在 TypeORM 中,您可以使用 Active Record 和 Data Mapper 模式。

使用 Active Record 方法,您可以在模型本身中定义所有查询方法,使用模型方法保存、删除和加载对象。

简单来说,Active Record 模式是一种在模型中访问数据库的方法。您可以在 Wikipedia 上了解更多关于 Active Record 模式的信息。

示例:

import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from "typeorm"

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

@Column()
firstName: string

@Column()
lastName: string

@Column()
isActive: boolean
}

所有的 active-record 实体都必须扩展 BaseEntity 类,该类提供了处理实体的方法。如何处理这样的实体的示例:

// 示例:如何保存 AR 实体
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await user.save()

// 示例:如何删除 AR 实体
await user.remove()

// 示例:如何加载 AR 实体
const users = await User.find({ skip: 2, take: 5 })
const newUsers = await User.findBy({ isActive: true })
const timber = await User.findOneBy({ firstName: "Timber", lastName: "Saw" })

BaseEntity 具有标准 Repository 的大部分方法。大部分时候,您不需要在 active record 实体中使用 RepositoryEntityManager

现在假设我们想要创建一个按姓和名返回用户的函数。我们可以将此类函数作为 User 类中的静态方法创建:

import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from "typeorm"

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

@Column()
firstName: string

@Column()
lastName: string

@Column()
isActive: boolean

static findByName(firstName: string, lastName: string) {
return this.createQueryBuilder("user")
.where("user.firstName = :firstName", { firstName })
.andWhere("user.lastName = :lastName", { lastName })
.getMany()
}
}

像其他方法一样使用它:

const timber = await User.findByName("Timber", "Saw")

什么是 Data Mapper 模式?

在 TypeORM 中,您可以使用 Active Record 和 Data Mapper 模式。

使用 Data Mapper 方法,您可以在称为 "repositories" 的单独类中定义所有查询方法,并使用存储库保存、删除和加载对象。在 data mapper 中,您的实体非常简单 - 它们只是定义它们的属性,可能有一些 "dummy" 方法。

简单来说,数据映射器是一种在存储库而非模型中访问数据库的方法。您可以在 Wikipedia 上了解更多关于 Data Mapper 模式的信息。

示例:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"

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

@Column()
firstName: string

@Column()
lastName: string

@Column()
isActive: boolean
}

如何处理这样的实体的示例:

const userRepository = dataSource.getRepository(User)

// 示例:如何保存 DM 实体
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await userRepository.save(user)

// 示例:如何删除 DM 实体
await userRepository.remove(user)

// 示例:如何加载 DM 实体
const users = await userRepository.find({ skip: 2, take: 5 })
const newUsers = await userRepository.findBy({ isActive: true })
const timber = await userRepository.findOneBy({
firstName: "Timber",
lastName: "Saw",
})

为了使用自定义方法扩展标准存储库,请使用 custom repository pattern

我应该选择哪个?

这个决定取决于您。这两种策略各有利弊。

我们在软件开发过程中应始终牢记如何维护我们的应用程序。Data Mapper 方法有助于维护性,在较大的应用程序中更有效。Active Record 方法有助于保持简单,适用于较小的应用程序。而简单性总是更好维护性的关键。