NodeJS 的Express 中集成 MySQL 和 Knex 的完整指南(一)

199 阅读3分钟

在 Express 中集成 MySQLKnex 的完整指南,包含依赖安装、配置方法及 Knex 的详细使用示例:


一、安装依赖

npm install mysql2 knex dotenv
  • mysql2: MySQL 驱动(支持 Promise)
  • knex: SQL 查询构建器(支持事务、链式调用)
  • dotenv: 环境变量管理(用于保护数据库配置)

二、配置 MySQL 连接

1. 创建 .env 文件

在项目根目录新建 .env,配置数据库信息:

DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=your_database
DB_PORT=3306

2. 创建 Knex 配置文件

新建 knexfile.js

require('dotenv').config();

module.exports = {
  development: {
    client: 'mysql2',
    connection: {
      host: process.env.DB_HOST,
      user: process.env.DB_USER,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      port: process.env.DB_PORT
    },
    migrations: {
      directory: './db/migrations' // 迁移文件目录
    },
    seeds: {
      directory: './db/seeds' // 种子数据目录
    }
  }
};

3. 初始化 Knex 实例

新建 db.js 文件:

const knex = require('knex');
const config = require('../knexfile');
const db = knex(config.development);

module.exports = db;

三、Knex 核心使用方法

1. 数据表操作(迁移)

创建迁移文件(需安装 knex 全局命令行工具):

npx knex migrate:make create_users_table

编辑生成的迁移文件(如 db/migrations/202310010000_create_users_table.js):

exports.up = function(knex) {
  return knex.schema.createTable('users', (table) => {
    table.increments('id').primary();
    table.string('name').notNullable();
    table.string('email').unique();
    table.timestamps(true, true); // 自动生成 created_at 和 updated_at
  });
};

exports.down = function(knex) {
  return knex.schema.dropTable('users');
};

执行迁移:

npx knex migrate:latest

2. 增删改查(CRUD)

插入数据
const db = require('./db');

// 插入单条
await db('users').insert({
  name: 'Alice',
  email: 'alice@example.com'
});

// 批量插入
await db('users').insert([
  { name: 'Bob', email: 'bob@example.com' },
  { name: 'Charlie', email: 'charlie@example.com' }
]);
查询数据
// 查询所有用户
const users = await db('users').select('*');

// 条件查询(单个结果)
const user = await db('users')
  .where({ id: 1 })
  .first();

// 条件查询(多个结果)
const activeUsers = await db('users')
  .where('status', 'active')
  .select('id', 'name');
更新数据
await db('users')
  .where({ id: 1 })
  .update({
    name: 'Alice Smith',
    email: 'alice.smith@example.com'
  });
删除数据
await db('users')
  .where({ id: 2 })
  .delete();

3. 复杂查询

单表多条件查询
const results = await db('users')
  .where('age', '>', 18)
  .andWhere('status', 'active')
  .orWhere('email', 'like', '%@gmail.com')
  .orderBy('created_at', 'desc');
分页查询
const page = 1;
const perPage = 10;

const paginatedData = await db('users')
  .select('*')
  .offset((page - 1) * perPage)
  .limit(perPage)
  .orderBy('id', 'asc');
聚合查询
const count = await db('users')
  .count('id as total')
  .where('status', 'active')
  .first();

4. 多表联合查询

内连接(INNER JOIN)
const orders = await db('orders')
  .join('users', 'orders.user_id', 'users.id')
  .select(
    'orders.id as order_id',
    'users.name as user_name',
    'orders.total_amount'
  )
  .where('users.status', 'active');
左连接(LEFT JOIN)
const products = await db('products')
  .leftJoin('categories', 'products.category_id', 'categories.id')
  .select(
    'products.name',
    'categories.name as category_name'
  );
子查询
const topUsers = await db('users')
  .whereIn('id', function() {
    this.select('user_id')
      .from('orders')
      .groupBy('user_id')
      .havingRaw('SUM(total_amount) > ?', [1000]);
  });

5. 事务处理

try {
  await db.transaction(async (trx) => {
    // 扣减库存
    await trx('products')
      .where('id', 1)
      .decrement('stock', 1);

    // 创建订单
    const [orderId] = await trx('orders')
      .insert({
        user_id: 1,
        total_amount: 99.99
      });

    // 提交事务
    return orderId;
  });
} catch (error) {
  console.error('Transaction failed:', error);
}

四、最佳实践

  1. 参数化查询
    始终使用 Knex 的查询构建方法,避免手动拼接 SQL 防止注入。
  2. 环境分离
    knexfile.js 中配置不同环境(开发、测试、生产)。
  3. 连接池管理
    在 Knex 配置中添加连接池参数:
    pool: {
      min: 2,
      max: 10
    }
    
  4. 错误处理
    使用 try/catch 包裹数据库操作,捕获可能的异常。

五、总结

通过 Knex,Express 项目可以高效、安全地操作 MySQL 数据库。其链式 API 支持复杂的查询逻辑,同时保持代码可读性。结合迁移和种子功能,能够实现数据库版本控制和测试数据管理。对于需要更高性能的场景,可进一步探索 Knex 的流式查询(Streams)和原始 SQL 执行能力。


本文使用到的npx,在 npx 的详细说明 中进行了介绍。
NodeJS 的Express 中集成 MySQL 和 Knex 的完整指南(二)中记录了Knex怎么在已有表添加新字段以及添加多个新表的操作