告别复杂SQL:Egg.js + Sequelize 零基础ORM实战指南

告别复杂SQL:Egg.js + Sequelize 零基础ORM实战指南

【免费下载链接】egg 🥚 Born to build better enterprise frameworks and apps with Node.js & Koa 【免费下载链接】egg 项目地址: https://gitcode.com/gh_mirrors/egg11/egg

你是否还在为手写SQL语句繁琐易错而烦恼?是否在多表关联查询中迷失方向?本文将带你从零开始,通过Egg.js框架集成Sequelize(对象关系映射,Object-Relational Mapping),用面向对象的方式操作数据库,彻底摆脱SQL依赖。读完本文你将掌握:环境配置、模型定义、CRUD操作、事务管理四大核心技能,让数据库操作像操作JavaScript对象一样简单。

框架架构概览

Egg.js作为企业级Node.js框架,采用分层架构设计,Sequelize作为ORM层衔接Service与数据库,形成清晰的数据处理流程。

Egg.js框架架构

Egg.js框架分层架构,ORM层位于Service与数据库之间(项目路径:gh_mirrors/egg11/egg)

环境准备与安装

项目初始化

确保已安装Node.js(v14+)和npm,通过Egg.js脚手架创建项目:

mkdir egg-sequelize-demo && cd egg-sequelize-demo
npm init egg --type=simple
npm install

安装核心依赖

安装Sequelize相关插件:

npm install egg-sequelize --save
npm install mysql2 --save # MySQL驱动

插件配置

config/plugin.js中启用egg-sequelize插件:

// config/plugin.js
exports.sequelize = {
  enable: true,
  package: 'egg-sequelize',
};

数据库配置(config/config.default.js):

// config/config.default.js
exports.sequelize = {
  dialect: 'mysql',
  host: 'localhost',
  port: 3306,
  database: 'egg-sequelize-demo',
  username: 'root',
  password: 'your_password',
  define: {
    timestamps: true, // 自动添加 createdAt/updatedAt 字段
    deletedAt: true,  // 软删除,添加 deletedAt 字段
    underscored: true // 字段驼峰转下划线
  }
};

数据模型定义

模型文件结构

Egg.js推荐将模型文件放在app/model目录下,每个文件对应一个数据表:

app/
└── model/
    ├── user.js      # 用户模型
    └── post.js      # 文章模型

定义用户模型

创建app/model/user.js

// app/model/user.js
module.exports = app => {
  const { STRING, INTEGER, DATE } = app.Sequelize;

  const User = app.model.define('user', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true },
    username: { type: STRING(30), allowNull: false, unique: true },
    email: { type: STRING(100), validate: { isEmail: true } },
    age: { type: INTEGER, defaultValue: 0 },
    created_at: DATE,
    updated_at: DATE,
    deleted_at: DATE
  });

  return User;
};

模型关联示例

创建文章模型app/model/post.js并关联用户:

// app/model/post.js
module.exports = app => {
  const { STRING, TEXT, INTEGER, DATE } = app.Sequelize;

  const Post = app.model.define('post', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true },
    title: { type: STRING(200), allowNull: false },
    content: TEXT,
    user_id: { 
      type: INTEGER,
      references: {
        model: 'user', // 关联用户表
        key: 'id'
      }
    }
  });

  // 定义关联关系:一篇文章属于一个用户
  Post.belongsTo(app.model.User, { foreignKey: 'user_id', as: 'author' });
  
  return Post;
};

CRUD操作实战

Service层封装

按照Egg.js最佳实践,数据库操作应封装在Service层:

// app/service/user.js
const Service = require('egg').Service;

class UserService extends Service {
  async create(user) {
    // 创建用户
    return this.ctx.model.User.create(user);
  }

  async findByPk(id) {
    // 根据主键查询
    return this.ctx.model.User.findByPk(id);
  }

  async findAll() {
    // 查询所有用户(支持分页)
    const { page = 1, limit = 10 } = this.ctx.query;
    const offset = (page - 1) * limit;
    return this.ctx.model.User.findAndCountAll({
      limit,
      offset,
      attributes: { exclude: ['password'] } // 排除敏感字段
    });
  }

  async update(id, updates) {
    // 更新用户
    const user = await this.ctx.model.User.findByPk(id);
    if (!user) {
      this.ctx.throw(404, '用户不存在');
    }
    return user.update(updates);
  }

  async destroy(id) {
    // 软删除用户
    const user = await this.ctx.model.User.findByPk(id);
    if (!user) {
      this.ctx.throw(404, '用户不存在');
    }
    return user.destroy();
  }
}

module.exports = UserService;

Controller调用示例

// app/controller/user.js
const Controller = require('egg').Controller;

class UserController extends Controller {
  async create() {
    const { ctx } = this;
    const user = await ctx.service.user.create(ctx.request.body);
    ctx.status = 201;
    ctx.body = user;
  }

  async show() {
    const { ctx } = this;
    const user = await ctx.service.user.findByPk(ctx.params.id);
    ctx.body = user;
  }
}

module.exports = UserController;

路由配置

// app/router.js
module.exports = app => {
  const { router, controller } = app;
  router.resources('users', '/api/users', controller.user);
};

高级查询与关联

多表关联查询

查询文章及其作者信息:

// app/service/post.js
async findWithAuthor(id) {
  return this.ctx.model.Post.findByPk(id, {
    include: [{
      model: this.ctx.model.User,
      as: 'author',
      attributes: ['id', 'username', 'email']
    }]
  });
}

复杂条件查询

async findAdvanced() {
  return this.ctx.model.User.findAndCountAll({
    where: {
      age: { [this.app.Sequelize.Op.gt]: 18 }, // 年龄大于18
      createdAt: {
        [this.app.Sequelize.Op.between]: [
          new Date('2023-01-01'),
          new Date('2023-12-31')
        ]
      }
    },
    order: [['createdAt', 'DESC']],
    limit: 10
  });
}

事务管理

Sequelize提供两种事务管理方式,推荐使用自动事务作用域:

// app/service/order.js
async createOrder(data) {
  const { ctx } = this;
  // 使用事务作用域自动管理事务
  return ctx.model.transaction(async t => {
    // 创建订单
    const order = await ctx.model.Order.create(data, { transaction: t });
    // 扣减库存
    await ctx.model.Product.decrement(
      { stock: data.quantity },
      { where: { id: data.productId }, transaction: t }
    );
    return order;
  });
}

迁移与种子文件

创建迁移文件

npx sequelize-cli migration:generate --name=init-users

编辑迁移文件:

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      username: {
        type: Sequelize.STRING(30),
        allowNull: false,
        unique: true
      },
      // 其他字段...
    });
  },

  down: async (queryInterface) => {
    await queryInterface.dropTable('users');
  }
};

执行迁移:

npx sequelize-cli db:migrate

常见问题与最佳实践

性能优化

  1. 按需加载字段:attributes: ['id', 'name']
  2. 使用索引:在频繁查询的字段上添加索引
  3. 批量操作:使用bulkCreatebulkUpdate

错误处理

try {
  await this.ctx.model.User.create(userData);
} catch (error) {
  if (error.name === 'SequelizeUniqueConstraintError') {
    this.ctx.throw(400, '用户名已存在');
  }
  throw error;
}

学习资源与进阶

通过本文的指南,你已掌握Egg.js集成Sequelize的核心技能。ORM不仅简化了数据库操作,更提供了数据验证、关联查询等高级特性,让你专注于业务逻辑而非SQL语法。开始在你的项目中实践这些知识,体验现代化数据库操作的便捷与高效!

【免费下载链接】egg 🥚 Born to build better enterprise frameworks and apps with Node.js & Koa 【免费下载链接】egg 项目地址: https://gitcode.com/gh_mirrors/egg11/egg

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值