在现代 Web 开发中,我们有很多便捷的工具和库可以让你用更直观的方式操作数据库,而不是直接写 SQL 查询。下面我来详细介绍几种便捷的方式,尤其是在 Node.jsExpress.js 环境下常用的工具。


1. 使用 ORM(对象关系映射)工具

ORM 工具是开发者最常用的一种方式,它允许你使用对象的形式与数据库交互,而不需要直接写 SQL。ORM 会自动生成 SQL 语句,并与数据库通信。

常见的 ORM 工具:

  1. Sequelize

    • 支持数据库:MySQL、PostgreSQL、SQLite、MSSQL
    • 特点
      • 定义模型(Model),每个模型对应数据库中的一张表。
      • 提供丰富的 API,如 .findAll().create().update() 等。
      • 支持复杂的查询、关联表操作(如一对一、一对多)。
    • 示例代码
      const { Sequelize, DataTypes } = require('sequelize');
      const sequelize = new Sequelize('database', 'username', 'password', {
          host: 'localhost',
          dialect: 'mysql',
      });
      
      // 定义模型
      const User = sequelize.define('User', {
          username: { type: DataTypes.STRING, allowNull: false },
          email: { type: DataTypes.STRING, allowNull: false },
      });
      
      // 创建记录
      (async () => {
          await sequelize.sync(); // 同步模型到数据库
          await User.create({ username: 'Alice', email: 'alice@example.com' });
          const users = await User.findAll();
          console.log(users);
      })();
      
  2. TypeORM

    • 支持数据库:MySQL、PostgreSQL、MariaDB、SQLite 等
    • 特点
      • 支持 TypeScript,非常适合有类型安全需求的项目。
      • 提供装饰器(decorators)来定义模型。
    • 示例代码
      import { Entity, PrimaryGeneratedColumn, Column, createConnection } from 'typeorm';
      
      @Entity()
      class User {
          @PrimaryGeneratedColumn()
          id;
      
          @Column()
          username;
      
          @Column()
          email;
      }
      
      (async () => {
          const connection = await createConnection({
              type: 'mysql',
              host: 'localhost',
              username: 'root',
              password: 'password',
              database: 'test',
              entities: [User],
              synchronize: true,
          });
      
          const userRepository = connection.getRepository(User);
          await userRepository.save({ username: 'Bob', email: 'bob@example.com' });
          const users = await userRepository.find();
          console.log(users);
      })();
      
  3. Prisma

    • 支持数据库:PostgreSQL、MySQL、SQLite、MongoDB 等
    • 特点
      • Schema 文件驱动,自动生成类型安全的客户端。
      • 查询方式直观,类似链式调用。
    • 示例代码
      const { PrismaClient } = require('@prisma/client');
      const prisma = new PrismaClient();
      
      (async () => {
          await prisma.user.create({
              data: {
                  username: 'Charlie',
                  email: 'charlie@example.com',
              },
          });
      
          const users = await prisma.user.findMany();
          console.log(users);
      })();
      

2. 使用 Query Builder 工具

如果你希望在不直接写 SQL 的同时又保留更多控制权,可以使用 Query Builder。这种工具允许你用链式 API 构建查询语句。

常见的 Query Builder:

  1. Knex.js

    • 支持数据库:MySQL、PostgreSQL、SQLite、MSSQL
    • 特点
      • 提供灵活的链式 API 构建查询。
      • 支持事务、批量插入等高级功能。
    • 示例代码
      const knex = require('knex')({
          client: 'mysql',
          connection: {
              host: '127.0.0.1',
              user: 'your_database_user',
              password: 'your_database_password',
              database: 'myapp_test',
          },
      });
      
      // 插入数据
      (async () => {
          await knex('users').insert({ username: 'Dave', email: 'dave@example.com' });
          const users = await knex('users').select('*');
          console.log(users);
      })();
      
  2. Objection.js

    • 支持数据库:基于 Knex.js,支持所有 Knex.js 支持的数据库。
    • 特点
      • 在 Query Builder 的基础上,增加了 ORM 的功能。
      • 支持定义模型和关联关系。
    • 示例代码
      const { Model } = require('objection');
      const Knex = require('knex');
      
      const knex = Knex({
          client: 'mysql',
          connection: {
              host: '127.0.0.1',
              user: 'your_database_user',
              password: 'your_database_password',
              database: 'myapp_test',
          },
      });
      
      Model.knex(knex);
      
      class User extends Model {
          static get tableName() {
              return 'users';
          }
      }
      
      (async () => {
          await User.query().insert({ username: 'Eve', email: 'eve@example.com' });
          const users = await User.query().select();
          console.log(users);
      })();
      

3. 使用数据库驱动的高阶封装

如果你不喜欢 ORM 或 Query Builder,也可以直接用数据库的官方驱动,但是通过封装函数和模块的方式来提高便捷性。

示例:

const mysql = require('mysql2/promise');

(async () => {
    const connection = await mysql.createConnection({
        host: 'localhost',
        user: 'root',
        database: 'test',
    });

    // 封装查询函数
    async function query(sql, params) {
        const [rows] = await connection.execute(sql, params);
        return rows;
    }

    // 使用封装的函数
    await query('INSERT INTO users (username, email) VALUES (?, ?)', ['Frank', 'frank@example.com']);
    const users = await query('SELECT * FROM users');
    console.log(users);
})();

4. 数据库即服务的集成

如果你不想自己维护数据库,可以使用一些托管服务,它们通常提供 SDK,进一步简化操作:

  • Firebase Firestore(文档型数据库)
  • Supabase(PostgreSQL 托管服务)
  • PlanetScale(MySQL 托管服务)

使用这些工具时,可以通过官方 SDK 直接操作数据,而不是使用 SQL。


总结

  • 原生 SQL 提供了最大的控制力,但可能会显得繁琐。
  • ORM 工具(如 Sequelize、Prisma) 适合需要快速构建和维护的项目。
  • Query Builder(如 Knex.js) 适合需要更高灵活性的场景。
  • 对于简单需求,你也可以直接封装数据库驱动或使用托管服务。

选择哪种方式,主要取决于你的项目复杂度、团队技能水平以及性能需求。如果是初学者,建议从 SequelizePrisma 开始,因为它们更易于理解和使用!