MikroORM
本章节介绍用户如何在 midway 中使用 MikroORM。 MikroORM 是基于数据映射器、工作单元和身份映射模式的 Node.js 的 TypeScript ORM。
MikroORM 的官网文档在 这里。
相关信息:
| 描述 | |
|---|---|
| 可用于标准项目 | ✅ |
| 可用于 Serverless | ✅ |
| 可用于一体化 | ✅ |
| 包含独立主框架 | ❌ |
| 包含独立日志 | ❌ |
关于升级
- 从
v3.14.0版本的组件开始,支持 mikro v5/v6 版本,由于 mikro v5 到 v6 有较大的变化,如从 mikro 老版本升级请提前阅读 Upgrading from v5 to v6 - 组件示例已更新为 v6 版本
- MikroORM v7 已切换为 native ESM,并调整了装饰器包路径。v7 项目请使用
@midwayjs/mikro7,不要和@midwayjs/mikro混用。
安装组件
安装 mikro 组件,提供接入 mikro-orm 的能力。@midwayjs/mikro 对应 MikroORM v6。
$ npm i @midwayjs/mikro@4 @mikro-orm/core@^6 @mikro-orm/sqlite@^6 --save
或者在 package.json 中增加如下依赖后,重新安装。
{
"dependencies": {
"@midwayjs/mikro": "^4.0.0",
"@mikro-orm/core": "^6.0.2",
// ...
},
"devDependencies": {
// ...
}
}
同时,还需要引入对应数据库的适配包。
比如:
{
"dependencies": {
// sqlite
"@mikro-orm/sqlite": "^6.0.2",
// mysql
"@mikro-orm/mysql": "^6.0.2",
},
"devDependencies": {
// ...
}
}
更多驱动程序请查看 官方文档。
如果使用 MikroORM v7,请安装独立的 v7 组件。
$ npm i @midwayjs/mikro7@4 @mikro-orm/core@^7 @mikro-orm/decorators@^7 @mikro-orm/sqlite@^7 --save
对应 package.json 依赖如下。
{
"dependencies": {
"@midwayjs/mikro7": "^4.0.0",
"@mikro-orm/core": "^7.0.0",
"@mikro-orm/decorators": "^7.0.0",
"@mikro-orm/sqlite": "^7.0.0"
}
}
v7 使用 legacy TypeScript 装饰器时,Entity 装饰器需要从 @mikro-orm/decorators/legacy 导入,并在配置中显式设置 metadataProvider: ReflectMetadataProvider。同时,项目的 TypeScript 配置需要使用 moduleResolution: "nodenext"、"node20" 或 "bundler"。
引入组件
在 src/configuration.ts 引入 mikro 组件,示例如下。
// configuration.ts
import { Configuration } from '@midwayjs/core';
import * as mikro from '@midwayjs/mikro';
import { join } from 'path';
@Configuration({
imports: [
// ...
mikro // 加载 mikro 组件
],
importConfigs: [
join(__dirname, './config')
]
})
export class MainConfiguration {
}
基础使用
和其他 orm 框架类似,都是分为几个步骤:
- 1、定义 Entity
- 2、配置数据源
- 3、获取 EntityModel 进行调用
下面的更多 Entity 代码请查看 示例。
目录结构
一个基础的参考目录结构如下。
MyProject
├── src
│ ├── config
│ │ └── config.default.ts
│ ├── entity
│ │ ├── book.entity.ts
│ │ ├── index.ts
│ │ └── base.ts
│ ├── configuration.ts
│ └── service
├── .gitignore
├── package.json
├── README.md
└── tsconfig.json
定义 Entity
定义基础的 Entity。
// src/entity/BaseEntity.ts
import { PrimaryKey, Property } from '@mikro-orm/core';
export abstract class BaseEntity {
@PrimaryKey()
id!: number;
@Property()
createdAt: Date = new Date();
@Property({ onUpdate: () => new Date() })
updatedAt: Date = new Date();
}
定义实际的 Entity,包含一对多,多对多等关系。
// src/entity/book.entity.ts
import { Cascade, Collection, Entity, ManyToMany, ManyToOne, Property } from '@mikro-orm/core';
import { Author, BookTag, Publisher } from './index';
import { BaseEntity } from './base';
@Entity()
export class Book extends BaseEntity {
@Property()
title: string;
@ManyToOne(() => Author)
author: Author;
@ManyToOne(() => Publisher, { cascade: [Cascade.PERSIST, Cascade.REMOVE], nullable: true })
publisher?: Publisher;
@ManyToMany(() => BookTag)
tags = new Collection<BookTag>(this);
@Property({ nullable: true })
metaObject?: object;
@Property({ nullable: true })
metaArray?: any[];
@Property({ nullable: true })
metaArrayOfStrings?: string[];
constructor(title: string, author: Author) {
super();
this.title = title;
this.author = author;
}
}
配置数据源
mikro v5 和 v6 略有不同。
- mikro v6
- mikro v5
// src/config/config.default
import { Author, BaseEntity, Book, BookTag, Publisher } from '../entity';
import { join } from 'path';
import { SqliteDriver } from '@mikro-orm/sqlite';
export default (appInfo) => {
return {
mikro: {
dataSource: {
default: {
dbName: join(__dirname, '../../test.sqlite'),
driver: SqliteDriver, // 这里使用了 sqlite 做示例
allowGlobalContext: true,
// 实体形式
entities: [Author, Book, BookTag, Publisher, BaseEntity],
// 支持如下的扫描形式,为了兼容我们可以同时进行.js和.ts匹配️
entities: [
'entity', // 指定目录
'**/entity/*.entity.{j,t}s', // 通配加后缀匹配
],
}
}
}
}
}
// src/config/config.default
import { Author, BaseEntity, Book, BookTag, Publisher } from '../entity';
import { join } from 'path';
export default (appInfo) => {
return {
mikro: {
dataSource: {
default: {
dbName: join(__dirname, '../../test.sqlite'),
type: 'sqlite', // 这里使用了 sqlite 做示例
allowGlobalContext: true,
// 实体形式
entities: [Author, Book, BookTag, Publisher, BaseEntity],
// 支持如下的扫描形式,为了兼容我们可以同时进行.js和.ts匹配️
entities: [
'entity', // 指定目录
'**/entity/*.entity.{j,t}s', // 通配加后缀匹配
],
}
}
}
}
}
提示
mikro 的 entities 字段配置已经经过框架处理,该字段配置请不要参考原始文档。