Sequelize 操作 MySQL 数据库(模型定义同步)

125 阅读4分钟

安装

Object Relational Mapping 对象关系映射 通过ORM框架,可以自动的把程序中的对象和 数据库关联。

ORM框架会隐藏具体的数据库底层细节,让开发者使用同样的数据操作接口,完成对不同数据库的操作。

npm install --save sequelize

安装驱动程序:

npm install --save mysql2

连接到数据库

要连接到数据库,必须创建一个 Sequelize 实例. 这可以通过将连接参数分别传递到 Sequelize 构造函数或通过传递一个连接 URI 来完成:

const {Sequelize} = require("sequelize");
// 创建数据库连接
const sequelize = new Sequelize('jingmao', 'root', 'root', {
    host: 'localhost',
    dialect: 'mysql',
    logging: false, // 生成的sql语句不在控制台打印
})
// 测试连接
async function MyFn() {
    try {
        await sequelize.authenticate();
        console.log('Connection has been established successfully.');
    } catch (error) {
        console.error('Unable to connect to the database:', error);
    }
}

MyFn();

Sequelize 构造函数接受很多参数. 它们记录在 API 参考中.

在 app.js 中引入文件,执行测试。

require('./dao/dbConnect')

Express 中使用 Sequelize

连接和初始化数据库

dbConnect.js

const {Sequelize} = require("sequelize");
// 创建数据库连接
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
    host: process.env.DB_HOST,
    dialect: 'mysql',
    logging: false, // 生成的sql语句不在控制台打印 默认值 logging: console.log
})
// 以对象的形式暴露
module.exports = sequelize;

这里使用了 dotenv 这个库 将一些环境变量写到 .env 中,将 .env 添加到 precess.env ,便于管理。 file_1720237969820_562.png

db.js

// 初始化数据库
const sequelize = require('./dbConnect'); // 数据库连接实例
const adminModel = require('./model/adminModel');// 管理员模型
const bannerModel = require('./model/bannerModel');
const md5 = require("md5");
const blogTypeModel = require("./model/blogTypeModel");
const blogModel = require('./model/blogModel');
const messageModel = require('./model/messageModel');

(async function () {
    // 定义模型之间的关联关系

    // 文章与文章分类之间的关联
    blogTypeModel.hasMany(blogModel, {foreignKey: 'categoryId', targetKey: 'id'})
    blogModel.belongsTo(blogTypeModel, {foreignKey: 'categoryId', targetKey: 'id', as: 'category'})
    // 文章和评论之间的关联
    blogModel.hasMany(messageModel, {foreignKey: 'blogId', targetKey: 'id'})
    messageModel.belongsTo(blogModel, {foreignKey: 'blogId', targetKey: 'id', as: 'blog'})

    // 同步模型和数据表(一次性同步所有模型)
    await sequelize.sync({
        alter: true
    })
    // 如果没有数据,则初始化管理员数据
    const adminCount = await adminModel.count()
    if (!adminCount) {
        await adminModel.create({
            loginId: 'admin',
            name: '超级管理员',
            loginPwd: md5('123456'),
        })
        console.log('初始化管理员数据成功')
    }
    // banner 初始化操作
    const bannerCount = await bannerModel.count()
    if (!bannerCount) {
        await bannerModel.bulkCreate([{
            "midImg": "/static/images/bg1_mid.jpg",
            "bigImg": "/static/images/bg1_big.jpg",
            "title": "塞尔达旷野之息",
            "description": "2017年年度游戏,期待续作"
        }, {
            "midImg": "/static/images/bg2_mid.jpg",
            "bigImg": "/static/images/bg2_big.jpg",
            "title": "塞尔达四英杰",
            "description": "四英杰里面你最喜欢的又是谁呢"
        }, {
            "midImg": "/static/images/bg3_mid.jpg",
            "bigImg": "/static/images/bg3_big.jpeg",
            "title": "日本街道",
            "description": "动漫中经常出现的日本农村街道,一份独特的恬静"
        }])
        console.log('初始化首页标语数据成功')
    }
    console.log('数据库初始化完成')
})()

模型同步:

当然除了一次性同步所有模型,也可以同步单个模型。

  • User.sync() - 如果表不存在,则创建该表(如果已经存在,则不执行任何操作)
  • User.sync({ force: true }) - 将创建表,如果表已经存在,则将其首先删除
  • User.sync({ alter: true }) - 这将检查数据库中表的当前状态(它具有哪些列,它们的数据类型等),然后在表中进行必要的更改以使其与模型匹配.

表关联:

A.hasOne(B) 关联意味着 A 和 B 之间存在一对一的关系,外键在目标模型(B)中定义.

A.belongsTo(B)关联意味着 A 和 B 之间存在一对一的关系,外键在源模型中定义(A).

A.hasMany(B) 关联意味着 A 和 B 之间存在一对多关系,外键在目标模型(B)中定义.

这三个调用将导致 Sequelize 自动将外键添加到适当的模型中(除非它们已经存在).

A.belongsToMany(B, { through: 'C' }) 关联意味着将表 C 用作联结表,在 A 和 B 之间存在多对多关系. 具有外键(例如,aId 和 bId). Sequelize 将自动创建此模型 C(除非已经存在),并在其上定义适当的外键.

app.js

// 捕获异步错误
require("express-async-errors")
// 默认读取项目根目录下的 .env 环境变量文件
require('dotenv').config()
// 引入数据库连接
require('./dao/db')

adminModel.js

const {DataTypes} = require("sequelize")
const sequelize = require("../dbConnect")
// 定义数据表
module.exports = sequelize.define("admin", {
    // id 自动生成 无需手动定义
    loginId: {
        type: DataTypes.STRING,
        allowNull: false,
    },
    loginPwd: {
        type: DataTypes.STRING,
        allowNull: false,
    },
    name: {
        type: DataTypes.STRING,
        allowNull: false
    }
}, {
    freezeTableName: true, // 禁止默认的自动复数化
    createdAt: false, // 创建表的时间,关闭默认字段
    // 或者也可以自定义名称 createdAt: "create_time"
    updatedAt: false, // 修改表的时间,关闭默认字段
    // tableNameL "administrators", // 手动定义表名
    // paranoid: true, // 该表的数据不会真正删除,而是增加一列deletedAt记录删除时间(逻辑删除时间)
})

自动复数化,比如给出模型名称为 user,那么表名自动为 users 。

操作数据库

const adminModel = require('./model/adminModel')
module.exports.loginDao = async function(loginInfo) {
    return await adminModel.findOne({
        where: {
            loginId: loginInfo.loginId,
            loginPwd: loginInfo.loginPwd
        }
    })
}

image.png