Node.js + MySQL - 用Sequelize & MySQL2连接到MySQL数据库

922 阅读3分钟

使用Node.jsSequelizeMySQL构建的教程

其他版本可用。

这是一个快速的帖子,展示如何使用Sequelize和MySQL2从Node.js连接到MySQL,并从代码中自动创建/更新MySQL数据库。

下面的代码片段来自我最近发布的Node.js + MySQL CRUD API教程,关于完整的项目和如何在本地运行的说明,请看Node.js + MySQL - CRUD API实例和教程

MySQL数据库封装器

MySQL数据库封装器使用Sequelize和mysql2 库连接到MySQL。它导出了一个对象,暴露了应用程序的所有数据库模型(目前只有User ),并提供了一个简单的方法,从一个点访问数据库的任何部分。

MySQL2是Sequelize用来连接到MySQL db服务器的MySQL连接器库。DB包装器直接使用mysql2 ,以连接到MySQL,如果数据库不存在,则创建数据库。关于MySQL2的更多信息见github.com/sidorares/n…

initialize() 函数在API启动时执行一次,执行以下操作。

  • 使用mysql2 db客户端连接到MySQL db服务器,如果API数据库还不存在,则执行查询以创建该数据库。
  • 用Sequelize ORM连接到API数据库。
  • 初始化User 模型并将其附加到导出的db 对象上。
  • 通过调用await sequelize.sync({ alter: true }) ,自动创建/更新MySQL数据库中的表以匹配Sequelize模型(如果需要)。关于Sequelize模型同步选项的更多信息见sequelize.org/master/manu…
const config = require('config.json');
const mysql = require('mysql2/promise');
const { Sequelize } = require('sequelize');

module.exports = db = {};

initialize();

async function initialize() {
    // create db if it doesn't already exist
    const { host, port, user, password, database } = config.database;
    const connection = await mysql.createConnection({ host, port, user, password });
    await connection.query(`CREATE DATABASE IF NOT EXISTS \`${database}\`;`);

    // connect to db
    const sequelize = new Sequelize(database, user, password, { dialect: 'mysql' });

    // init models and add them to the exported db object
    db.User = require('../users/user.model')(sequelize);

    // sync all models with database
    await sequelize.sync({ alter: true });
}

Sequelize用户模型

路径。/users/user.model.js

用户模型使用Sequelize来定义MySQL数据库中users 表的模式。导出的Sequelize模型对象给出了在MySQL中对用户执行CRUD(创建、读取、更新、删除)操作的完整权限,请参阅下面的用户服务,了解它的使用实例(通过db helper)。

defaultScope 将模型配置为默认从查询结果中排除密码哈希值。withHash 范围可用于查询用户并在结果中包括密码哈希。关于Sequelize作用域的更多信息见sequelize.org/master/manu…

const { DataTypes } = require('sequelize');

module.exports = model;

function model(sequelize) {
    const attributes = {
        email: { type: DataTypes.STRING, allowNull: false },
        passwordHash: { type: DataTypes.STRING, allowNull: false },
        title: { type: DataTypes.STRING, allowNull: false },
        firstName: { type: DataTypes.STRING, allowNull: false },
        lastName: { type: DataTypes.STRING, allowNull: false },
        role: { type: DataTypes.STRING, allowNull: false }
    };

    const options = {
        defaultScope: {
            // exclude password hash by default
            attributes: { exclude: ['passwordHash'] }
        },
        scopes: {
            // include hash with this scope
            withHash: { attributes: {}, }
        }
    };

    return sequelize.define('User', attributes, options);
}

用户服务

路径。/users/user.service.js

用户服务负责所有的数据库交互和与用户CRUD操作相关的核心业务逻辑,它封装了与Sequelize用户模型的所有交互,并暴露了一组简单的方法来访问和管理MySQL中的数据。

文件的顶部包含导出的服务对象,仅有方法名称,以便于一目了然地看到所有的方法,文件的其余部分包含每个服务方法的实现函数,然后是本地辅助函数。

const bcrypt = require('bcryptjs');

const db = require('_helpers/db');

module.exports = {
    getAll,
    getById,
    create,
    update,
    delete: _delete
};

async function getAll() {
    return await db.User.findAll();
}

async function getById(id) {
    return await getUser(id);
}

async function create(params) {
    // validate
    if (await db.User.findOne({ where: { email: params.email } })) {
        throw 'Email "' + params.email + '" is already registered';
    }

    const user = new db.User(params);
    
    // hash password
    user.passwordHash = await bcrypt.hash(params.password, 10);

    // save user
    await user.save();
}

async function update(id, params) {
    const user = await getUser(id);

    // validate
    const usernameChanged = params.username && user.username !== params.username;
    if (usernameChanged && await db.User.findOne({ where: { username: params.username } })) {
        throw 'Username "' + params.username + '" is already taken';
    }

    // hash password if it was entered
    if (params.password) {
        params.passwordHash = await bcrypt.hash(params.password, 10);
    }

    // copy params to user and save
    Object.assign(user, params);
    await user.save();
}

async function _delete(id) {
    const user = await getUser(id);
    await user.destroy();
}

// helper functions

async function getUser(id) {
    const user = await db.User.findByPk(id);
    if (!user) throw 'User not found';
    return user;
}