Skip to main content
Version: 6.4

实体存储库

实体存储库是 EntityManager 之上的薄层。它们充当扩展点,因此你可以添加自定义方法,甚至更改现有方法。默认的 EntityRepository 实现只是将调用转发到底层 EntityManager 实例。

¥Entity Repositories are thin layers on top of EntityManager. They act as an extension point, so you can add custom methods, or even alter the existing ones. The default EntityRepository implementation just forwards the calls to underlying EntityManager instance.

EntityRepository 类带有实体类型,因此你不必将其传递给每个 findfindOne 调用。

¥EntityRepository class carries the entity type, so you do not have to pass it to every find or findOne calls.

const booksRepository = em.getRepository(Book);

// same as `em.find(Book, { author: '...' }, { ... })`
const books = await booksRepository.find({ author: '...' }, {
populate: ['author'],
limit: 1,
offset: 2,
orderBy: { title: QueryOrder.DESC },
});

console.log(books); // Book[]

自定义存储库

¥Custom Repository

信息

自 v4 以来,我们需要确保使用正确类型的 EntityRepositorycreateQueryBuilder() 才能访问 方法。使用从驱动程序包中导出的选项。

¥Since v4, you need to make sure you are working with correctly typed EntityRepository to have access to driver specific methods (like createQueryBuilder()). Use the one exported from your driver package.

要使用自定义存储库,只需扩展 EntityRepository<T> 类:

¥To use custom repository, just extend EntityRepository<T> class:

import { EntityRepository } from '@mikro-orm/mysql'; // or any other driver package

export class CustomAuthorRepository extends EntityRepository<Author> {

// custom methods...
public findAndUpdate(...) {
// ...
}

}

并通过 @Entity 装饰器注册存储库:

¥And register the repository via @Entity decorator:

@Entity({ repository: () => CustomAuthorRepository })
export class Author {
// ...
}

@Repository() 装饰器已在 v5 中删除,请改用 @Entity({ repository: () => MyRepository })

¥@Repository() decorator has been removed in v5, use @Entity({ repository: () => MyRepository }) instead.

请注意,你需要在回调中传递该存储库引用,这样在该存储库内使用实体引用时就不会遇到循环依赖问题。

¥Note that you need to pass that repository reference inside a callback so you will not run into circular dependency issues when using entity references inside that repository.

现在你可以通过 em.getRepository() 方法访问你的自定义存储库。

¥Now you can access your custom repository via em.getRepository() method.

推断自定义存储库类型

¥Inferring custom repository type

要使 em.getRepository() 方法返回正确类型的自定义存储库而不是通用的 EntityRepository<T>,你可以使用 EntityRepositoryType 符号:

¥To have the em.getRepository() method return correctly typed custom repository instead of the generic EntityRepository<T>, you can use EntityRepositoryType symbol:

@Entity({ repository: () => AuthorRepository })
export class Author {

[EntityRepositoryType]?: AuthorRepository;

}

const repo = em.getRepository(Author); // repo has type AuthorRepository

你还可以通过 MikroORM.init({ entityRepository: CustomBaseRepository }) 全局注册自定义基础存储库(针对所有未指定 repository 的实体)。

¥You can also register custom base repository (for all entities where you do not specify repository) globally, via MikroORM.init({ entityRepository: CustomBaseRepository }).

EntityRepository 接口中删除方法

¥Removed methods from EntityRepository interface

自 v6 以来,以下方法在 EntityRepository 实例上不再可用:

¥Following methods are no longer available on the EntityRepository instance since v6:

  • persist

  • persistAndFlush

  • remove

  • removeAndFlush

  • flush

它们令人困惑,因为它们给人一种使用范围上下文的虚假感觉(例如,仅使用 User 类型),而实际上,它们只是底层 EntityManager 的相同方法的快捷方式。当涉及到实体持久性时,你应该直接使用 EntityManager,而不是使用存储库,存储库应被视为自定义逻辑的扩展点(例如封装查询构建器使用)。

¥They were confusing as they gave a false sense of working with a scoped context (e.g. only with a User type), while in fact, they were only shortcuts for the same methods of underlying EntityManager. You should work with the EntityManager directly instead of using a repository when it comes to entity persistence, repositories should be treated as an extension point for custom logic (e.g. wrapping query builder usage).

或者,你可以使用 repository.getEntityManager() 方法直接在 EntityManager 上访问这些方法。

¥Alternatively, you can use the repository.getEntityManager() method to access those methods directly on the EntityManager.

如果你想将这些方法保留在存储库级别,你可以定义自定义基础存储库并全局使用它:

¥If you want to keep those methods on repository level, you can define custom base repository and use it globally:

import { EntityManager, EntityRepository, AnyEntity } from '@mikro-orm/mysql';

export class ExtendedEntityRepository<T extends object> extends EntityRepository<T> {

persist(entity: AnyEntity | AnyEntity[]): EntityManager {
return this.em.persist(entity);
}

async persistAndFlush(entity: AnyEntity | AnyEntity[]): Promise<void> {
await this.em.persistAndFlush(entity);
}

remove(entity: AnyEntity): EntityManager {
return this.em.remove(entity);
}

async removeAndFlush(entity: AnyEntity): Promise<void> {
await this.em.removeAndFlush(entity);
}

async flush(): Promise<void> {
return this.em.flush();
}

}

并在 ORM 配置中指定它:

¥And specify it in the ORM config:

MikroORM.init({
entityRepository: ExtendedEntityRepository,
})

你可能还想使用 EntityRepositoryType 符号,可能在自定义基础实体中。

¥You might as well want to use the EntityRepositoryType symbol, possibly in a custom base entity.