简介
Sequelize 是一个基于promise的 Node.js ORM(对象关系映射库—Object-Relational Mapping Library)。它具有强大的事务支持,关联关系,预读和延迟加载,读取复制等功能。
它将所有的SQL语句代码映射到Javascript对象中(封装),然后导出变成我们可调用的方法,这样我们就不用自己编写SQL语句代码。
例如:
INSERT INTO users VALUE ('Jon', 28, 'HJDFKLS')
——>
const user = User.create({ name: 'Jon', age: 28, password: 'HJDFKLS'})
安装
注意:sequelize需要安装数据库的驱动程序,我使用的数据库是MySQL,所以需要安装mysql2包!
npm install --save sequelize
使用
连接数据库
database.js
const Sequelize = require('sequelize'); // 引入sequelize
const sequelize = new Sequelize('node-complete', 'root', 'rootpassword', { // 数据库的库名,用户名,密码以及其他配置
dialect: 'mysql', // 数据库语言
host: 'localhost', // 连接服务器
});
module.exports = sequelize; // @1
@1:导出的sequelize对象本质上也是数据库连接池(同mysql2连接),只不过通过sequelize管理后我们能使用其他的一些功能。
定义新模型
使用define()来定义一个新的模型(数据表),它的第一个参数为模型名称(表名),第二个参数为模型的各个参数(表中字段):
models/product.js
const Sequelize = require('sequelize');
const sequelize = require('../util/database');
const Product = sequelize.define('product', {
id: {
type: Sequelize.INTEGER, // 类型
autoIncrement: true, // 是否自增
allowNull: false, // 是否为Null
primaryKey: true // 主键
},
title: Sequelize.STRING,
price: {
type: Sequelize.DOUBLE,
allowNull: false
},
imageUrl: {
type: Sequelize.STRING,
allowNull: false
},
description: {
type: Sequelize.STRING,
allowNull: false
}
});
module.exports = Product;
创建新的表
将创建的模型转为数据库中的表:
app.js
...
const sequelize = require('./util/database');
sequelize
.sync() // @2
.then(result => {
app.listen(3000);
})
.catch(err => {
console.log(err);
});
...
注:如果数据库中没有这个表,则创建;如果已经存在这个表则不会覆盖原先的表。
@2:如果已经创建了表,想要新建一个覆盖原来的表,可以设置force:
.sync( { force: true })
表创建完需删除force,避免每次更新项目都重新创建新表。
之后数据库会自动创建一个与模型字段及信息对应的表。
向表中新增一条数据
通过create()向表中新增一条数据:
...
const Product = require('../models/product');
router.post('/product', (req, res, next) => {
const title = req.body.title;
const imageUrl = req.body.imageUrl;
const price = req.body.price;
const description = req.body.description;
Product.create({
title: title,
price: price,
imageUrl: imageUrl,
description: description
})
.then(result => {
console.log('Created Product');
res.redirect('/admin/products');
})
.catch(err => {
console.log(err);
})
});
查询表中数据
findAll()
通过findAll()来查询表中所有数据:
查询表中所有数据:
router.get('/products', (req, res, next) => {
Product.findAll()
.then(products => {
res.render('shop/index', {
prods: products,
pageTitle: 'Shop',
path : "/",
});
})
.catch(err => console.log(err));
});
查询id为prodId的数据:
router.get('/products/:productId', (req, res, next) => {
const prodId = req.params.productId;
Product.findAll({ where: { id: prodId} })
.then(products => {
res.render('shop/index', {
prods: products[0],
pageTitle: products[0].title,
path : "/products",
});
})
.catch(err => console.log(err));
});
注意:通过where子句返回的then的参数是一个数组。
findByPk()
使用提供的主键从表中仅获得一条数据:
const Product = require('../models/product');
// 此处主键在数据库中为id
router.get('/products/:productId', (req, res, next) => {
const prodId = req.params.productId;
Product.findByPk(prodId)
.then((product) => {
res.render('shop/product-detail', {
product: product,
pageTitle: product.title,
path: '/products'
})
})
.catch(err => console.log(err));
});
修改表中数据
通过主键(id)找到对应数据后,在本地修改数据,修改完后通过save()方法将修改完的数据发送给数据库,如果数据库中存在修改的数据就覆盖它,如果不存在就新建它:
...
router.post('/edit-product', (req, res, next) => {
const prodId = req.body.productId;
const updatedTitle = req.body.title;
const updatedPrice = req.body.price;
const updatedImageUrl = req.body.imageUrl;
const updatedDesc = req.body.description;
Product.findByPk(prodId)
.then(product => {
product.title = updatedTitle; // 在本地修改数据
product.price = updatedPrice; // 在本地修改数据
product.description = updatedDesc; // 在本地修改数据
product.imageUrl = updatedImageUrl; // 在本地修改数据
return product.save(); // 将修改好的数据发给数据库,返回一个Promise
})
.then(result => {
console.log('UPDATED PRODUCT!');
res.redirect('/admin/products');
})
.catch(err => console.log(err));
});
...
删除数据
通过destroy()来删除数据:
删除指定ID数据:
...
router.post('/delete-product', (req, res, next) => {
const prodId = req.body.productId;
Product.findByPk(prodId)
.then(product => {
return product.destroy();
})
.then(result => {
console.log('DESTROYED PRODUCT');
res.redirect('/admin/products');
})
.catch(err => console.log(err));
});
也可以通过destroy()的where语句来进行指定删除。
关联
Sequelize 支持标准关联关系:一对一、一对多和多对多。
为此,Sequelize 提供了四种关联类型,并将它们组合起来以创建关联:
HasOne 关联类型
BelongsTo 关联类型
HasMany 关联类型
BelongsToMany 关联类型
一对一
每个User只有一个Cart,Cart属于User:
...
User.hasOne(Cart);
Cart.belongsTo(User);
...
一对多
Product属于User,每个User可以有多个Product:
...
Product.belongsTo(User, {
constraints: true, // 开启定义关系约束
onDelete: 'CASCADE' // 级联删除
});
User.hasMany(Product);
...
多对多
一个Cart里可以有多个Product,每个Product可以在不同的Cart中:
...
Cart.belongsToMany(Product, {
through: CartItem // 这些连接存储的位置
});
Product.belongsToMany(Cart, { through: CartItem });
...
添加到实例的特殊方法
当两个模型之间定义了关联时,这些模型的实例将获得特殊的方法来与其关联的另一方进行交互。
// 定义Product和User的关系
Product.belongsTo(User, {
constraints: true, // 开启定义关系约束
onDelete: 'CASCADE' // 级联删除
});
User.hasMany(Product);
createXXX()
使用instance.createProduct()来创建Product将会自动生成关联User的id:
const Product = require('../models/product');
router.post('/product', (req, res, next) => {
const title = req.body.title;
const imageUrl = req.body.imageUrl;
const price = req.body.price;
const description = req.body.description;
// 创建Product模型,并自动添加userId(关联主键)
req.user.createProduct({ // req.user是sequelize保存在数据库中的数据(一个辅助方法)
title: title,
price: price,
imageUrl: imageUrl,
description: description,
})
.then(result => {
console.log('Created Product');
res.redirect('/admin/products');
})
.catch(err => {
console.log(err);
})
});
getXXX()
使用instance.getProducts()来获取Product:
router.get('/edit-product/:productId',(req, res, next) => {
const editMode = req.query.edit;
if (!editMode) {
return res.redirect('/')
}
const prodId = req.params.productId;
req.user
.getProducts({ where: { id: prodId } }) // 获取对应id的Product
// Product.findByPk(prodId) // 也可以使用findByPk()来寻找
.then(products => {
const product = products[0];
if (!product) {
return res.redirect('/');
}
res.render('admin/edit-product',{
pageTitle: 'Edit Product',
path: '/admin/edit-product',
editing: editMode,
product: product
});
})
.catch(err => console.log(err));
});
addXXX()
使用instance.addProducts()来添加Product:
...
addProduct(product, {
through: { quantity: newQuantity }
});
})
...