1 教你如何用js去操作数据库 mysql-orm学习笔记

Node.js ORM - Sequelize

基本

概述:基于Promise的ORM(Object Relation Mapping),支持多种数据库、事务、关联等
安装: npm i sequelize mysql2 -S
基本使用

const Sequelize = require("sequelize");

// 建立连接
const sequelize = new Sequelize("kaikeba", "root", "admin", {
    host: "localhost",
    dialect: "mysql",
    operatorsAliases: false
});

// 定义模型
const Fruit = sequelize.define("Fruit", {
    name: {type: Sequelize.STRING(20), allowNull: false},
    price: {type: Sequelize.FLOAT, allowNull: false},
    stock: {type: Sequelize.INTEGER, defaultValue: 0}
});

// 同步数据库,force: true则会删除已存在表
Fruit.sync().then(() => {
    // 添加测试数据    
    return Fruit.create({name: "香蕉", price: 3.5});
}).then(() => {
    // 查询    
    Fruit.findAll().then(fruits => {
        console.log(JSON.stringify(fruits));
    });
});

强制同步是什么?如何使用?(会重置已有的表)

Fruit.sync({force: true})

表是默认生成时间戳的,如何去掉?

const Fruit = sequelize.define("Fruit", {}, {  timestamps: false });

指定表名: freezeTableName: true 或 tableName:'xxx'

设置前者则以modelName作为表名;设置后者则按其值作为表名。

Getters & Setters有什么作用?:可用于定义伪属性或映射到数据库字段的保护属性

// 定义为属性的一部分
name: {
    type: Sequelize.STRING, 
    allowNull :false, 
    get(){
        const fname = this.getDataValue("name");
        const price = this.getDataValue("price");
        const stock = this.getDataValue("stock");
        return `${fname}(价格:¥${price} 库存:${stock}kg)`;
    }
}

// 定义为模型选项 
{
    getterMethods:{
        amount()
        {
            return this.getDataValue("stock") + "kg";
        }
    },
    setterMethods:{
        amount(val)
        {
            const idx = val.indexOf('kg');
            const v = val.slice(0, idx);
            this.setDataValue('stock', v);
        }
    }
}

// 通过模型实例触发setterMethods
Fruit.findAll().then(fruits => {
    console.log(JSON.stringify(fruits));
    // 修改amount,触发setterMethods    
    fruits[0].amount = '150kg';
    fruits[0].save();
});

如何进行校验?:可以通过校验功能验证模型字段格式、内容,校验会在 create 、 update 和 save 时自动运行

price: {
    validate: {
        isFloat: {msg: "价格字段请输入数字"},
        min: {args: [0], msg:"价格字段必须大于0"}
    }
},
stock: {
    validate: {
        isNumeric: {msg: "库存字段请输入数字"}
    }
}

如何进行模型扩展?:可添加模型实例方法或类方法扩展模型

// 添加类级别方法
Fruit.classify = function (name) {
    const tropicFruits = ['香蕉', '芒果', '椰子'];
    // 热带水果  
    return tropicFruits.includes(name) ? '热带水果':'其他水果'; };

// 添加实例级别方法
    Fruit.prototype.totalPrice = function (count) {
        return (this.price * count).toFixed(2);
    };

// 使用类方法
    ['香蕉', '草莓'].forEach(f => console.log(f + '是' + Fruit.classify(f)));

// 使用实例方法
    Fruit.findAll().then(fruits => {
        const [f1] = fruits;
        console.log(`买5kg${f1.name}需要¥${f1.totalPrice(5)}`);
    });

增删改查

1增

    ret = await Fruit.create({
        name: "香蕉",
        price: 3.5
    })

2删

// 方式1 
Fruit.findOne({ where: { id: 1 } }).then(r => r.destroy());
 
// 方式2 
Fruit.destroy({ where: { id: 1 } }).then(r => console.log(r));

3改

// 方式1  
Fruit.findById(1).then(fruit => {
    fruit.price = 4;
    fruit.save().then(() => console.log('update!!!!'));
});
// 方式2 
Fruit.update({price: 4}, {where: {id: 1}}).then(r => {
    console.log(r);
    console.log('update!!!!')
})

4查 op链接(https://www.cnblogs.com/zhaom...

// 通过属性查询
Fruit.findOne({where: {name: "香蕉"}}).then(fruit => {
    // fruit是首个匹配项,若没有则为null    
    console.log(fruit.get());
});

// 获取数据和总条数
Fruit.findAndCountAll().then(result => {
    console.log(result.count);
    console.log(result.rows.length);
});

// 查询操作符
const Op = Sequelize.Op;
Fruit.findAll({
// where: { price: { [Op.lt()]:4 }, stock: { [Op.gte()]: 100 } }  
    where: {price: {[Op.lt]: 4, [Op.gt]: 2}}
}).then(fruits => {
    console.log(fruits.length);
});

// 或语句
Fruit.findAll({
    // where: { [Op.or]:[{price: { [Op.lt]:4 }}, {stock: { [Op.gte]: 100 }}] }  
    where: {price: {[Op.or]: [{[Op.gt]: 3}, {[Op.lt]: 2}]}}
}).then(fruits => {
    console.log(fruits[0].get());
});

// 分页
Fruit.findAll({offset: 0, limit: 2,})

// 排序
Fruit.findAll({order: [['price', 'DESC']],})

// 聚合
setTimeout(() => {
    Fruit.max("price").then(max => {
        console.log("max", max)
    })
    Fruit.sum("price").then(sum => {
        console.log("sum", sum);
    });
}, 500)

4-2关联查询

关联

//1:N关系
const Player = sequelize.define('player', {name: Sequelize.STRING});
const Team = sequelize.define('team', {name: Sequelize.STRING});

// 会添加teamId到Player表作为外键
Player.belongsTo(Team);// 1端建立关系
Team.hasMany(Player); // N端建立关系

// 同步
sequelize.sync({force: true}).then(async () => {
    await Team.create({name: '火箭'});
    await Player.bulkCreate([{name: '哈登', teamId: 1}, {name: '保罗', teamId: 1}]);
// 1端关联查询    
    const players = await Player.findAll({include: [Team]});
    console.log(JSON.stringify(players, null, '\t'));
// N端关联查询  
    const team = await Team.findOne({where: {name: '火箭'}, include: [Player]});
    console.log(JSON.stringify(team, null, '\t'));
});


// 多对多关系
const Fruit = sequelize.define("fruit", {name: Sequelize.STRING});
const Category = sequelize.define("category", {name: Sequelize.STRING});
Fruit.FruitCategory = Fruit.belongsToMany(
    Category, {through: "FruitCategory"}
);

Web前端路上
Web前端路上,专注Vue,html5,css3等

爱前端,爱生活

662 声望
15 粉丝
0 条评论
推荐阅读
1 PHP
typora-copy-images-to: images1.1 今日目标掌握互联网的工作原理掌握域名、DNS和IP地址之间的关系理解hosts文件在互联网访问过程中的作用理解静态网站和动态网站的区别理解动态网站的服务器组成了解PHP的工作过...

曦沙飞舞阅读 702

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木66阅读 6.1k评论 16

从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木43阅读 7.3k评论 6

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木33阅读 6.2k评论 9

从零搭建 Node.js 企业级 Web 服务器(五):数据库访问
回顾 从零搭建 Node.js 企业级 Web 服务器(一):接口与分层,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,控制层与服务层实现了业务处理过程,模型层定义了业务实体并以 对象-关系...

乌柏木34阅读 4.6k评论 9

从零搭建 Node.js 企业级 Web 服务器(十三):断点调试与性能分析
Node.js 官方提供了断点调试机制,出于安全性考虑默认为关闭状态,可以通过 node 参数 --inspect 或 --inspect-brk 开启,配合 IDE 能够非常方便地调试代码,本章就上一章已完成的项目 licg9999/nodejs-server-ex...

乌柏木31阅读 3.9k评论 9

从零搭建 Node.js 企业级 Web 服务器(八):网络安全
计算机网络依据 TCP/IP 协议栈分为了物理层、网络层、传输层、应用层,通常基础设施供应商会解决好前三层的网络安全问题,需要开发者自行解决应用层的网络安全问题,本章将着重表述应用层常见的网络安全问题及处...

乌柏木33阅读 5.8k评论 1

爱前端,爱生活

662 声望
15 粉丝
宣传栏