使用Node.js、Sequelize和MySQL构建的教程
其他版本可用。
这是一个快速的帖子,展示如何使用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启动时执行一次,执行以下操作。
- 使用
mysql2db客户端连接到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;
}