Node.js SQL数据库操作 (下)(ORM框架Sequelize模块及案例展示)
Posted YuLong~W
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.js SQL数据库操作 (下)(ORM框架Sequelize模块及案例展示)相关的知识,希望对你有一定的参考价值。
ORM框架
ORM(Object Relational Mapping,对象关系映射),是一种为了 解决面向对象与关系数据库存在的互不匹配的现象 的技术,通过描述对象和数据库之间映射的 元数据,把程序中的对象自动持久化到关系数据库中。它的作用是在关系型数据库和对象之间作一个映射,这样,在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。
持久(Persistence)化,即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。
- ORM就是把 业务实体中的对象 与 关系数据库中的关系数据 关联起来,对数据库进行高层封装
- 对象-关系映射(ORM)系统一般以中间件的形式存在
- 不足之处主要是会牺牲程序的执行效率
ORM技术特点:
- 提高了开发效率。ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
- ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
Sequelize模块
- Sequelize 是一款基于Promise的支持异步操作的Node.js ORM框架,能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect)。
- 支持Postgres、mysql、SQLite和Microsoft SQL Server等多种数据库,具有强大的事务支持、关联关系、读取和复制等功能。
- 很适合作为Node.js后端数据库的存储接口,有助于提高Node.js应用程序的开发效率。
特点:
- 强大的模型定义,支持虚拟类型
- 支持完善的数据验证,减轻前后端的验证压力
- Sequelize的查询非常全面和灵活
Sequelize的基本使用
安装sequelize库:npm install --save sequelize
基本用法:
1、建立连接:
- 第1种方式:单独传递参数(多数)
const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: /*可以是'mysql'、'mariadb'、'postgres'或'mssql'中任何一个 */
});
- 第2种方式:传递连接URL
const Sequelize = require('sequelize');
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
示例:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('testmydb', 'root', 'abc123', {
//连接选项
host: 'localhost', // 数据库地址
dialect: 'mysql', // 指定连接的数据库类型
pool: {
max: 5, // 连接池的最大连接数量
min: 0, // 连接池的最小连接数量
idle: 10000 // 如果一个线程10秒钟内没有被使用,那么就释放线程
}
});
//测试连接
sequelize
.authenticate()
.then(() => {
console.log('成功建立连接');
})
.catch(err => {
console.error('未能连接到数据库:', err);
});
2、定义模型:
- ① 使用 Sequelize.Model.init(attributes, options)函数
const Model = Sequelize.Model;
class User extends Model {}
User.init({
// 属性设置
name: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING
// allowNull(允许空值)默认为true
}
}, {
sequelize,
modelName: 'user' //此处定义模型名
// 选项
});
- ② 使用 sequelize.define(‘name’, {attributes}, {options})
const User = sequelize.define('user', { // user为模型名
// 属性
name: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING
}
}, { // 选项
});
3、将模型与数据库同步(可选)
User.sync({ force: true }).then(() => {
// 数据库中的表与模型定义一致
return User.create({
name: '小莉',
email: 'xiaoli@abc.com'
});
});
- 选项 force: true 表示如果表已经存在,在新建前会删除原表
4、增加操作:
// 创建新的用户
User.create({ name: "小彤", email: "xiaotong@abc.com" }).then(() => {
console.log("已添加");
});
5、删除操作:
// 删除名为小红的用户
User.destroy({
where: {
name: "小红"
}
}).then(() => {
console.log("已删除");
});
6、更改操作:
// 将没有邮箱的用户的邮箱改为it@abc.com
User.update({ eamil: "it@abc.com" }, {
where: {
email: null
}
}).then(() => {
console.log("已改完");
});
7、查找操作:
// 查找所有用户
User.findAll().then(users => {
console.log("所有用户:", JSON.stringify(users, null, 4));
});
Promises和async/await
- Sequelize使用Promise来控制异步操作流程,增查改删操作都可使用then()方法。
- 如果Node.js版本支持,可以使用ES2017 async/await语法来编写Sequelize所用的异步调用代码。
- Sequelize的所有Promise对象也是Bluebird的Promise对象,也可以使用Bluebird API来操作。
- Sequelize返回的Promise对象也可以通过co模块来操作。
Sequelize的多表关联
源和目标:
const User = sequelize.define('user',{
name: Sequelize.STRING,
email: Sequelize.STRING
});
const Project = sequelize.define('project',{
name: Sequelize.STRING
});
User.hasOne(Project);
外键:
- Sequelize创建模型之间的关联时,将自动创建带有约束的外键引用
- 创建Task和User模型之间的关系会在tasks表中插入外键userId,并将该外键作为对users表的引用
const Task = sequelize.define('task', {
title: Sequelize.STRING
});
const User = sequelize.define('user', {
username: Sequelize.STRING
});
User.hasMany(Task); // 自动将userId添加到Task模型
Task.belongsTo(User); //也会自动将userId添加到Task模型
一对一关联:
- belongsTo关联
- belongsTo关联在源模型上存在一对一关系的外键
示例:Player通过players表的外键teamId作为Team的一部分
const Player = sequelize('player',{
/* 属性定义 */
});
const Team = sequelize('team', {
/* 属性定义 */
});
Player.belongsTo(Team); // 向Team模型添加teamId属性以保存Team的主键值
一对一关联:
- hasOne关联
- hasOne关联是在目标模型上存在的一对一关系的外键的关联
示例:向User模型添加projectId属性
const User = sequelize.define('user', {
/* ... */
});
const Project = sequelize.define('project',{
/* ... */
});
Project.hasOne(User) // 单向关联
hasOne和belongsTo之间的区别:
- hasOne在目标模型中插入关联键
- belongsTo在源模型中插入关联键
示例:
const Player = sequelize.define('player', {/* 属性定义 */});
const Coach = sequelize.define('coach', {/* 属性定义 */});
const Team = sequelize.define('team', {/* 属性定义 */});
- 当有关关联的信息存在于源模型中时,可以使用belongsTo关联。例中Player适用于belongsTo关联,因为它具有teamId列。
Player.belongsTo(Team) // teamId 将被添加到源模型Player中
- 当有关关联的信息存在于目标模型中时,可以使用hasOne关联。例中Coach适用于hasOne关联,因为Team模型将其Coach的信息存储为coachId列。
Coach.hasOne(Team) // coachId将被添加到目标模型Team中
一对多关联:
- 一对多关联将一个源与多个目标连接起来,多个目标连接到同一个特定的源:
const User = sequelize.define('user', {/* ... */})
const Project = sequelize.define('project', {/* ... */})
Project.hasMany(User, {as: 'Workers'})
- hasMany() 用于定义一对多关联
- 要在不同的列上关联记录,可以使用sourceKey选项指定源键:
const City = sequelize.define('city', { countryCode: Sequelize.STRING });
const Country = sequelize.define('country', { isoCode: Sequelize.STRING });
// 可以根据国家代码连接国家和城市
Country.hasMany(City, {foreignKey: 'countryCode', sourceKey: 'isoCode'});
City.belongsTo(Country, {foreignKey: 'countryCode', targetKey: 'isoCode'});
多对多关联:
- 多对多关联用于将源与多个目标相连接,目标也可以连接到多个源:
Project.belongsToMany(User, {through: 'UserProject'});
User.belongsToMany(Project, {through: 'UserProject'});
图书借阅管理案例
此案例用于记录图书的借阅信息,为简化实验过程,只有两个表 books(图书)和 readers(读者),它们之间是一对多的关系,一种图书可以对应多个读者,使用自动建立表结构的方案。在实际的应用程序开发中,往往将数据部分独立出来,作为模型部分,这样有利于各模块的解耦和扩展。
1、定义图书数据模型:
const Sequelize = require('sequelize');
module.exports = (sequelize) => {
var Book = sequelize.define('book', {
isbn: { type: Sequelize.STRING },
name: { type: Sequelize.STRING },
author: { type: Sequelize.STRING },
press: { type: Sequelize.STRING },
price: { type: Sequelize.DECIMAL(10, 2) },
pubdate: { type: Sequelize.DATEONLY }
});
return Book;
};
2、定义读者数据模型:
const Sequelize = require('sequelize');
module.exports = (sequelize) => {
var Reader = sequelize.define('reader', {
name: { type: Sequelize.STRING },
mobile: { type: Sequelize.STRING },
email: { type: Sequelize.STRING }
});
return Reader;
};
3、同步数据模型:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('testmydb', 'root', 'abc123', {
//连接选项
host: 'localhost', // 数据库地址
dialect: 'mysql', // 指定连接的数据库类型
define: {
'charset':'utf8' //解决中文输入问题
},
pool: { // 建立连接池
max: 5, // 连接池的最大连接数量
min: 0, // 连接池的最小连接数量
idle: 20000 // 如果一个线程在20秒内没有被使用过,那么释放线程
}
});
const Book = require('./book_model')(sequelize);//导入Book模型
const Reader = require('./reader_model')(sequelize);//导入Reader模型
Book.hasMany(Reader); //一种图书有多个读者
Reader.belongsTo(Book); //一个读者对应一种图书
sequelize.sync(); //自动同步所有的模型,使用关联时要使用。首次添加数据之后可将其注释掉
exports.Book = Book;
exports.Reader = Reader;
4、添加数据:
const Book = require('./mydb').Book;
const Reader = require('./mydb').Reader;
async function addBook() {
const result = await Book.create(
{
isbn:"9787115474582",
//(此处略)
},
{ include: [Reader] } //指定关联关系,读者数据自动插入到读者表
);
return result;
}
addBook().then(data => {
console.log("添加的数据:", JSON.stringify(data, null, 4)); // 获取返回的内容
}).catch(error => {
console.log(error); // 捕获错误
});
5、获取数据:
const Book = require('./mydb').Book;
const Reader = require('./mydb').Reader;
async function getBook() {
const result = await Book.findAll();
return result;
}
getBook().then(data => {
console.log("查询的数据:", JSON.stringify(data, null, 4)); // 获取返回的内容
}).catch(error => {
console.log(error); // 捕获错误
});
6、更改数据:
const Book = require('./mydb').Book;
const Reader = require('./mydb').Reader;
async function updateBook() {
const result = await Book.update(
{ price:98.00 },
{ where: { id: 1 } }
);
return result;
}
updateBook().then(data => {
console.log("修改数据的ID:", JSON.stringify(data, null, 4)); // 获取返回的内容
}).catch(error => {
console.log(error); // 捕获错误
});
7、删除数据:
const Book = require('./mydb').Book;
const Reader = require('./mydb').Reader;
async function delBook() {
const result = await Book.destroy(
{ where: { id: 1 } }
);
return result;
}
delBook().then(data => {
console.log("删除数据的ID:", JSON.stringify(data, null, 4)); // 获取返回的内容
}).catch(error => {
console.log(error); // 捕获错误
以上是关于Node.js SQL数据库操作 (下)(ORM框架Sequelize模块及案例展示)的主要内容,如果未能解决你的问题,请参考以下文章
使用 ORM Sequelize / node.js 操作数据
像.net Entity Framework 这样的 Node JS 的 ORM?