fontcolor_theme
Deepkit Framework

数据库

Deepkit 具有自己强大的数据库抽象库,称为 Deepkit ORM。它是一款对象关系映射(ORM)库,可简化与 SQL 数据库和 MongoDB 的协作。

虽然你可以使用任意数据库库,但我们推荐 Deepkit ORM,因为它是最快的 TypeScript 数据库抽象库,与 Deepkit 框架深度集成,并拥有许多能提升工作流程与效率的特性。

本章解释如何在你的 Deepkit 应用中使用 Deepkit ORM。有关 Deepkit ORM 的完整信息,请参阅ORM章节。

数据库类

在应用中使用 Deepkit ORM 的 Database 对象的最简单方式,是注册一个从其派生的类。

import { Database } from '@deepkit/orm';
import { SQLiteDatabaseAdapter } from '@deepkit/sqlite';
import { User } from './models';

export class SQLiteDatabase extends Database {
    constructor() {
        super(
            new SQLiteDatabaseAdapter('/tmp/myapp.sqlite'), 
            [User]
        );
    }
}

创建一个新类,并在其构造函数中指定适配器及其参数;同时在第二个参数中添加所有应连接到此数据库的实体模型。

现在你可以将该数据库类注册为提供者(provider)。我们还启用 migrateOnStartup,它会在启动时自动在你的数据库中创建所有表。这非常适合快速原型开发,但不建议用于严肃项目或生产环境。此时应使用常规的数据库迁移。

我们还启用 debug,这样在应用服务器启动时可以打开调试器,并在内置的 ORM 浏览器中直接管理你的数据库模型。

import { App } from '@deepkit/app';
import { FrameworkModule } from '@deepkit/framework';
import { SQLiteDatabase } from './database.ts';

new App({
    providers: [SQLiteDatabase],
    imports: [
        new FrameworkModule({
            migrateOnStartup: true,
            debug: true,
        })
    ]
}).run();

现在你可以通过依赖注入在任意位置访问 SQLiteDatabase

import { SQLiteDatabase } from './database.ts';

export class Controller {
    constructor(protected database: SQLiteDatabase) {}

    @http.GET()
    async startPage(): Promise<User[]> {
        //返回所有用户
        return await this.database.query(User).find();
    }
}

配置

在许多情况下,你希望连接凭据是可配置的。比如,测试环境与生产环境使用不同的数据库。你可以通过 Database 类的 config 选项来实现。

//database.ts
import { Database } from '@deepkit/orm';
import { PostgresDatabaseAdapter } from '@deepkit/sqlite';
import { User } from './models';

type DbConfig = Pick<AppConfig, 'databaseHost', 'databaseUser', 'databasePassword'>;

export class MainDatabase extends Database {
    constructor(config: DbConfig) {
        super(new PostgresDatabaseAdapter({
            host: config.databaseHost,
            user: config.databaseUser,
            password: config.databasePassword,
        }), [User]);
    }
}
//config.ts
export class AppConfig {
    databaseHost: string = 'localhost';
    databaseUser: string = 'postgres';
    databasePassword: string = '';
}
//app.ts
import { App } from '@deepkit/app';
import { FrameworkModule } from '@deepkit/framework';
import { MainDatabase } from './database.ts';
import { AppConfig } from './config.ts';

const app = new App({
    config: AppConfig,
    providers: [MainDatabase],
    imports: [
        new FrameworkModule({
            migrateOnStartup: true,
            debug: true,
        })
    ]
});
app.loadConfigFromEnv({prefix: 'APP_', namingStrategy: 'upper', envFilePath: ['local.env', 'prod.env']});
app.run();

现在,由于我们使用了 loadConfigFromEnv,我们可以通过环境变量来设置数据库凭据。

APP_DATABASE_HOST=localhost APP_DATABASE_USER=postgres ts-node app.ts server:start

或者在 local.env 文件中设置,并在未预先设置任何环境变量的情况下启动 ts-node app.ts server:start

APP_DATABASE_HOST=localhost
APP_DATABASE_USER=postgres

多个数据库

你可以按需添加任意数量的数据库类,并为它们任意命名。请确保修改每个数据库的名称,以免在使用 Deepkit ORM 浏览器时与其他数据库冲突。

管理数据

现在你已经完成所有设置,可以使用 Deepkit ORM 浏览器来管理你的数据库数据。要打开 Deepkit ORM 浏览器并管理内容,请将上述所有步骤写入 app.ts 文件并启动服务器。

$ ts-node app.ts server:start
2021-06-11T15:08:54.330Z [LOG] Start HTTP server, using 1 workers.
2021-06-11T15:08:54.333Z [LOG] Migrate database default
2021-06-11T15:08:54.336Z [LOG] RPC DebugController deepkit/debug/controller
2021-06-11T15:08:54.337Z [LOG] RPC OrmBrowserController orm-browser/controller
2021-06-11T15:08:54.337Z [LOG] HTTP OrmBrowserController
2021-06-11T15:08:54.337Z [LOG]     GET /_orm-browser/query httpQuery
2021-06-11T15:08:54.337Z [LOG] HTTP StaticController
2021-06-11T15:08:54.337Z [LOG]     GET /_debug/:any serviceApp
2021-06-11T15:08:54.337Z [LOG] HTTP listening at http://localhost:8080/

现在你可以打开 http://localhost:8080/_debug/database/default。

你可以看到 ER(实体关系)图。目前只有一个实体可用。如果你添加了更多带关系的实体,你将一目了然地看到所有信息。

如果你在左侧侧栏点击 User,即可管理其内容。点击 + 图标并修改新记录的标题。更改所需的值(例如用户名)后,点击 Confirm。这会将所有更改提交到数据库并使之生效。自增 ID 会自动分配。

进一步了解

要进一步了解 SQLiteDatabase 的工作方式,请阅读数据库一章及其子章节,例如查询数据、通过会话操作数据、定义关系等。 请注意,那些章节针对的是独立库 @deepkit/orm,并不包含本章上文所述的 Deepkit 框架部分的文档。在独立库中,你需要手动实例化数据库类,例如通过 new SQLiteDatabase()。然而,在你的 Deepkit 应用中,这由依赖注入容器自动完成。

迁移

Deepkit 框架提供了强大的迁移系统,允许你创建、执行和回滚迁移。该迁移系统基于 Deepkit ORM 库,因此与框架完美集成。

FrameworkModule 提供了多个用于管理迁移的命令。

  • migration:create - 基于数据库差异生成新的迁移文件
  • migration:pending - 显示待执行的迁移文件
  • migration:up - 执行待执行的迁移文件
  • migration:down - 执行向下迁移,回滚旧的迁移文件
ts-node app.ts migration:create --migrationDir src/migrations

一个新的迁移文件会创建在 migrations 目录中。该目录是 FrameworkModule 中配置的默认目录。要更改它,可以通过环境变量(如配置一章所述)修改配置,或在构造 FrameworkModule 时传入 migrationDir 选项。

new FrameworkModule({
    migrationDir: 'src/migrations',
})

新创建的迁移文件现在包含 up 和 down 方法,它们基于你的 TypeScript 应用中定义的实体与已配置数据库之间的差异生成。 你可以根据需要修改 up 方法。down 方法会基于 up 方法自动生成。 将该文件提交到你的代码仓库,以便其他开发者也能执行它。

待执行的迁移

ts-node app.ts migration:pending --migrationDir src/migrations

这会显示所有待执行的迁移。如果你有尚未执行的新迁移文件,它会列在这里。

执行迁移

ts-node app.ts migration:up --migrationDir src/migrations

这将执行下一个待执行的迁移。

回滚迁移

ts-node app.ts migration:down --migrationDir src/migrations

这将回滚上一次执行的迁移。

伪迁移

假设你尝试执行一次迁移(向上或向下),但失败了。你手动修复了问题,但现在无法再次执行该迁移,因为它已被标记为已执行。此时可以使用 --fake 选项来伪装执行:在不实际执行的情况下,将该迁移在数据库中标记为已执行。这样你就可以继续执行下一个待执行的迁移。

ts-node app.ts migration:up --migrationDir src/migrations --fake
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)