技术栈:nodejs(type: module) + sequelize + mysql + dotenv-cli
代码仓库地址:https://gitee.com/Lxinz/db-use.git
Sequelize 基础准备
默认你已经完成docker部署mysql,并创建了db_use的数据库,设置了数据库账号root/123456。
1、如果没有安装sequelize、sequelize-cli、相关数据库(比如mysql2),需要先安装
npm install sequelize sequelize-cli mysql2
2、在对应目录下,初始化 Sequelize(生成配置、迁移、种子目录等)
npx sequelize-cli init
目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| project/ ├── config/ │ ├── .env.development │ └── .env.production ├── db/ │ ├── config/ │ │ └── config.js │ ├── models/ │ │ └── index.js │ ├── migrations/ │ │ └── [timestamp]-create-users-table.js │ └── seeders/ ├── .sequelizerc ├── package.json └── ...
|
3、数据库配置(用于迁移)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| export default { development: { username: process.env.DEV_DB_USERNAME, password: process.env.DEV_DB_PASSWORD, database: process.env.DEV_DB_DATABASE, host: process.env.DEV_DB_HOST, port: process.env.DEV_DB_PORT, dialect: process.env.DEV_DB_DIALECT, }, production: { username: process.env.PROD_DB_USERNAME, password: process.env.PROD_DB_PASSWORD, database: process.env.PROD_DB_DATABASE, host: process.env.PROD_DB_HOST, port: process.env.PROD_DB_PORT, dialect: process.env.PROD_DB_DIALECT, } };
|
上面使用了dotenv来读取环境变量,需要安装npm install dotenv。
这里使用了环境变量去配置数据库的信息,环境变量放置在根目录的config下(具体可查看目录结构)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # .env.development NODE_ENV=development DEV_DB_USERNAME=root DEV_DB_PASSWORD=123456 DEV_DB_DATABASE=db_use DEV_DB_HOST=localhost DEV_DB_PORT=3306 DEV_DB_DIALECT=mysql
# .env.production NODE_ENV=production PROD_DB_USERNAME=root PROD_DB_PASSWORD=123456 PROD_DB_DATABASE=db_use PROD_DB_HOST=localhost PROD_DB_PORT=3306 PROD_DB_DIALECT=mysql
|
上面环境变量通过dotenv-cli,在scripts脚本配置时,直接指向了对于目录的环境配置,因此可以在项目中直接使用process.env.NODE_ENV这样的方式调用环境变量。
1 2 3 4 5 6 7 8 9
| "scripts": { "serve": "dotenv -e config/.env.development node index.js", "serve:prod": "dotenv -e config/.env.production node index.js", "migrate:up": "dotenv -e config/.env.development npx sequelize-cli db:migrate --env=development", "migrate:undo": "dotenv -e config/.env.development npx sequelize-cli db:migrate:undo --env=development", "migrate:up:prod": "dotenv -e config/.env.production npx sequelize-cli db:migrate --env=production", "migrate:undo:prod": "dotenv -e config/.env.production npx sequelize-cli db:migrate:undo --env=production" },
|
Sequelize 表迁移步骤(生产推荐使用)
1、新建一个迁移文件
npx sequelize-cli migration:generate --name create-users-table
2、手动修改迁移文件内容(修改为ES语法、添加数据库字段)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| export default { up: async (queryInterface, Sequelize) => { await queryInterface.createTable('Users', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER, }, name: { type: Sequelize.STRING, }, email: { type: Sequelize.STRING, unique: true, }, createdAt: { allowNull: false, type: Sequelize.DATE, }, updatedAt: { allowNull: false, type: Sequelize.DATE, }, }); },
down: async (queryInterface, Sequelize) => { await queryInterface.dropTable('Users'); }, };
|
await queryInterface.dropTable(‘Users’)作用?
用于 回滚迁移的操作(undo migration),当执行npx sequelize-cli db:migrate会运行 up()
方法,创建 Users
表;当执行npx sequelize-cli db:migrate:undo会运行 down()
方法,这时候 dropTable('Users')
就会生效,把 Users
表删掉。
需要注意的是,个迁移文件的话,db:migrate:undo
只会回滚最后一个迁移文件。如果你想一次性回滚所有迁移,则执行npx sequelize-cli db:migrate:undo:all即可。
2、项目根目录配置.sequelizerc
这样可以在项目的根目录去执行迁移指令,或者封装到package.json的scripts中也可以正常使用了。
1 2 3 4 5 6 7 8 9 10
|
const path = require('path');
module.exports = { 'config': path.resolve('db', 'config', 'config.js'), 'models-path': path.resolve('db', 'models'), 'seeders-path': path.resolve('db', 'seeders'), 'migrations-path': path.resolve('db', 'migrations'), };
|
3、执行迁移
在项目根目录下执行:
npx sequelize-cli db:migrate --env=development
其中的 development
参数指的是你在 sequelize
初始化的 config/config.js
文件中配置的某一个环境;如果你不加 --env
参数,Sequelize CLI 默认使用 development
环境。
Sequelize 数据迁移-种子操作(Seed)
1、创建种子文件
npx sequelize-cli seed:generate --name update-user
2、编辑种子文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| export default { async up (queryInterface, Sequelize) {
await queryInterface.bulkInsert('Users', [{ name: 'John Doe', email: '12345678910@qq.com', createdAt: new Date(), updatedAt: new Date() }], {}); },
async down (queryInterface, Sequelize) {
await queryInterface.bulkDelete('Users', null, {}); } };
|
如果只更新表中指定的某条数据的部分字段,可以在up函数中的queryInterface.bulkInsert方法的第二个参数传入一个对象,第三个参数传入查询参数。
1 2 3 4 5
| await queryInterface.bulkUpdate( 'Users', { name: '李四' }, { id: 1 } );
|
3、执行种子插入
npx sequelize-cli db:seed:all --env=development
增删改查实操
1、在db/models下创建对应数据库的表模型,比如User.js,内容可以参考迁移文件中对应的表进行编写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| export default (sequelize, DataTypes) => { const Users = sequelize.define('Users', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, name: { type: DataTypes.STRING, }, email: { type: DataTypes.STRING, unique: true, }, }, { timestamps: true, freezeTableName: true, comment: '用户表', });
return Users; };
|
需要注意的是,如果迁移表中创建了createdAt、updatedAt等时间自动,可以在表模型文件中通过配置属性timestamps去实现自动创建和更新,也就不需要在表模型的字段定义中再次定义了。
如果是先写了表模型文件,想编写对应的迁移文件,就需要注意,如果有timestamps字段定义的,需要在迁移文件中自行创建。
之后,会在db/models/index.js中自动引入,并导出sequelize实例和表模型的一个对象db,通过db就可以进行数据库对应表的增删改查了。
2、比如以上面创建的Users表为例,在项目的根目录的入口index.js中实现增删改查。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import db from './db/models/index.js'; const { Users } = db;
const newUser = await Users.create({ name: 'Tom', email: 'tom@example.com' });
const User = await Users.findOne({ where: { email: 'tom@example.com' } }); console.log(User.toJSON());
await Users.update({ name: 'Tommy' }, { where: { email: 'tom@example.com' } });
await Users.destroy({ where: { email: 'tom@example.com' } });
|