Skip to content

SQL 和 ORM

SQL 数据库是在持久存储中存储应用程序数据的流行选择。你可以在 AdonisJS 应用程序中使用任何库和 ORM 来执行 SQL 查询。

TIP

AdonisJS 核心团队构建了 Lucid ORM,但不强制你使用它。你可以在 AdonisJS 应用程序中使用任何其他你喜欢的 SQL 库和 ORM。

流行选项

以下是你可以在 AdonisJS 应用程序中使用的其他流行 SQL 库和 ORM 列表(就像任何其他 Node.js 应用程序一样)。

  • Lucid 是一个建立在 Knex 之上的 SQL 查询构建器和 Active Record ORM,由 AdonisJS 核心团队创建和维护。
  • Prisma Prisma ORM 是 Node.js 生态系统中另一个流行的 ORM。它拥有大量的社区追随者。它提供直观的数据模型、自动迁移、类型安全和自动完成功能。
  • Kysely 是一个用于 Node.js 的端到端类型安全查询构建器。如果你需要一个没有任何模型的精简查询构建器,Kysely 非常适合。我们写了一篇文章解释如何在 AdonisJS 应用程序中集成 Kysely
  • Drizzle ORM 被我们社区中的许多 AdonisJS 开发者使用。我们没有使用这个 ORM 的经验,但你可能想看看它是否适合你的用例。
  • Mikro ORM 是 Node.js 生态系统中一个被低估的 ORM。与 Lucid 相比,MikroORM 有点冗长。但是,它得到积极维护,也建立在 Knex 之上。
  • TypeORM 是 TypeScript 生态系统中一个流行的 ORM。

使用其他 SQL 库和 ORM

当使用其他 SQL 库或 ORM 时,你需要手动更改某些包的配置。

认证

AdonisJS 认证模块内置支持使用 Lucid 获取已认证用户。当使用其他 SQL 库或 ORM 时,你需要实现 SessionUserProviderContractAccessTokensProviderContract 接口来获取用户。

以下是使用 Kysely 时如何实现 SessionUserProviderContract 接口的示例。

ts
import { symbols } from '@adonisjs/auth'
import type { SessionGuardUser, SessionUserProviderContract } from '@adonisjs/auth/types/session'
import type { Users } from '../../types/db.js' // Kysely 特定

export class SessionKyselyUserProvider implements SessionUserProviderContract<Users> {
  /**
   * 由事件发射器用于向会话守卫发出的事件添加类型信息。
   */   
  declare [symbols.PROVIDER_REAL_USER]: Users

  /**
   * 会话守卫和你的提供者之间的桥梁。
   */
  async createUserForGuard(user: Users): Promise<SessionGuardUser<Users>> {
    return {
      getId() {
        return user.id
      },
      getOriginal() {
        return user
      },
    }
  }

  /**
   * 使用你的自定义 SQL 库或 ORM 通过用户 ID 查找用户。
   */
  async findById(identifier: number): Promise<SessionGuardUser<Users> | null> {
    const user = await db
      .selectFrom('users')
      .selectAll()
      .where('id', '=', identifier)
      .executeTakeFirst()

    if (!user) {
      return null
    }

    return this.createUserForGuard(user)
  }
}

一旦你实现了 UserProvider 接口,你可以在配置中使用它。

ts
const authConfig = defineConfig({
  default: 'web',

  guards: {
    web: sessionGuard({
      useRememberMeTokens: false,
      provider: sessionUserProvider({
        model: () => import('#models/user'),
      }),
      
      provider: configProvider.create(async () => {
        const { SessionKyselyUserProvider } = await import(
          '../app/auth/session_user_provider.js' // 文件路径
        )

        return new SessionKyselyUserProvider()
      }),
    }),
  },
})