Active Record vs Data Mapper
Эта страница переведена PageTurner AI (бета). Не одобрена официально проектом. Нашли ошибку? Сообщить о проблеме →
Что такое паттерн Active Record?
В TypeORM вы можете использовать как паттерн Active Record, так и Data Mapper.
При подходе Active Record вы определяете все методы запросов внутри самой модели, а сохраняете, удаляете и загружаете объекты с помощью методов модели.
Проще говоря, паттерн Active Record — это подход для доступа к базе данных из ваших моделей. Подробнее о паттерне 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, который предоставляет методы для работы с сущностью.
Пример работы с такой сущностью:
// example how to save AR entity
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await user.save()
// example how to remove AR entity
await user.remove()
// example how to load AR entities
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.
В большинстве случаев вам не нужно использовать Repository или EntityManager с сущностями Active Record.
Допустим, мы хотим создать функцию, возвращающую пользователей по имени и фамилии.
Мы можем создать такую функцию как статический метод класса 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 вы определяете все методы запросов в отдельных классах, называемых "репозиториями", а сохраняете, удаляете и загружаете объекты с помощью репозиториев. В Data Mapper ваши сущности предельно просты — они только определяют свои свойства и могут содержать "простые" методы.
Проще говоря, Data Mapper — это подход для доступа к базе данных через репозитории вместо моделей. Подробнее о паттерне 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)
// example how to save DM entity
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await userRepository.save(user)
// example how to remove DM entity
await userRepository.remove(user)
// example how to load DM entities
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",
})
Для расширения стандартного репозитория пользовательскими методами используйте паттерн кастомного репозитория.
Какой подход выбрать?
Решение остается за вами. Обе стратегии имеют свои преимущества и недостатки.
При разработке программного обеспечения мы всегда должны помнить о том, как будем поддерживать наши приложения.
Подход Data Mapper способствует поддержке, что особенно эффективно в крупных приложениях.
Подход Active Record помогает сохранять простоту, что хорошо работает в небольших приложениях.