昨天我们说到使用node中的mysql 模块连接操作mysql 数据库,在文章的最后我们说到了可以使用Sequelize以完全的js 的形式创建,操作数据表, 那么我们今天就来说说Sequelize 具体应该怎么去使用
- 首先我们还是说一下前期的准备工作:
- 初始化一个node的开发项目: npm init -y
- 项目中安装上sequelize
- 安装上mysql2 (由于这里我们仍然是操作mysql 数据库, 其实sequelize 中使用mysql和mysql2 模块都是可以的,但今天试验的时候sequelize提示我使用mysql2, 所以我们这里就使用mysql2了)
使用Sequelize 的流程:
- 引入sequelize 模块并创建Sequelize 实例:
const Sequelize = require('sequelize')
// 创建一个基础的连接配置项
const conf = {
host: "localhost", // 连接数据库的域
dialect: "mysql" // 操作数据库的类型
}
// 创建sequelize 实例连接数据库:
/**
* 参数1: 连接数据库的名称
* 参数2: 数据库用户名
* 参数3: 数据库的密码
* 参数4: 一些连接的配置项
*/
const seq = new Sequelize('myblog', 'root', '13544425754', conf)
- 使用创建的Sequelize 实例参测试连接数据库
// 测试连接数据库: 使用authenticate() 函数返回Promise
// 注意: 这样的连接方式会一直保持连接,方便我们的开发操作,适合于开发环境下使用这种方式连接,在线上环境下推荐使用连接池, 连接池最后我们再提一下
seq.authenticate().then(() => {
console.log('数据库连接成功!')
}).catch(() => {
console.log("数据库连接失败!")
})
- 往数据库中创建数据表:
/**
* 使用seq 实例定义我们数据库中的表: define()定义一张数据表
* 创建数据表时我们不用考虑主键的东西,之直接写上我们实际需要的值,Sequeliz 会自动为我们的表中创建一个id项作为主键,
* 同时Sequelize 会将为我们的数据表中自动的创建createdAt项和updatedAt项
* define() 函数的参数:
* 参数1: 创建的表名称: 注意: 我们这里写入的表名称, Sequelize会自动的帮我们在名称后加's', 及这里我们写的'user', 实际的数据表名称是: 'users'
* 参数2: 表中的实际列表项
*/
//这里我们以建立一张user表为例:
const User = seq.define('user', {
username: {
type: Sequelize.STRING, // 定义列表项的数据类型: sequelize中的STRING默认表示的是: varchar(255)类型, 其他的数据类型也可以去网上查找
allowNull: false // 列表项是否允许为空
},
password: {
type: Sequelize.STRING,
allowNull: false
},
nickname: {
type: Sequelize.STRING,
comment: "昵称" // 使用comment 对于列表项进行描述
}
})
- 将Sequelize 创建的数据表同步到数据库:
// 这里我们创建的数据表实际在数据库中是还没有的,需要我们对Sequelize 和 数据库进行同步
/**
* 使用sync() 进行数据库的同步:
* 其中接收一个参数: force: true : 表示如果数据库中存在相同的数据表会进行强制删除, 然后替换上Sequelize中的表
* 函数返回的仍是一个Promise, 在回调中我们使用 process.exit()结束这个进程,避免sequelize一直占用着这个进程
*/
seq.sync({force: true}).then(() => {
console.log("sync ok")
process.exit()
})
- 往我们创建的数据表中添加数据项:
- 注意: 使用sync 同步数据表后需要将同步操作去掉,避免反复执行覆盖我们原本的数据表
/**
* 创建一个闭包往数据表中添加数据项
*/
!(async function(){
/*
* 使用创建的数据表上的create() 方法插入数据项, 参数为数据项的具体信息, 函数执行返回插入的数据信息, 为异步函数,所以这里我们使用了async await
*/
const zhangsan = await User.create({
username: 'zhangsan',
password: '123',
nickname: '张三'
})
// 插入操作后返回值的dataValues 属性可以得到插入数据的具体信息
console.log(zhangsan.dataValues)
})()
6. 数据查询操作:
!(async function() {
/**
* 查询一条数据: 使用数据表的findOne()方法查询一条数据:
* 参数:查询的条件等的一个对象列表
*/
const zhangsan = await User.findOne({
where: {
userName: 'zhangsan'
}
})
/**
* 加上 attributes 属性后可以具体查询数据表中的指定某些列:
* attributes 属性值为一个数组, 数组元素表示需要查询列的名称
*/
const zhangsanName = await User.findOne({
attributes: ['userName', 'nickName'],
where: {
userName: 'zhangsan'
}
})
/*
* 查询整个列表的所有满足要求的数据: 使用数据表的 findAll()方法
* 参数仍然是一个查询的条件的对象
*/
const UserList = await User.findAll({
where: {
userId: 1
},
order: [
['id', 'desc']
]
})
/*
* 分页查询: 使用limit配置项和offset 配置项进行分页查询:
*/
const limitUser = await User.findAll({
limit: 2, // 指定每次限定查询的数据条数
offset: 2, // 每次查询时需跳过多少条数据
order: [
['id', 'desc'] // 指定进行倒叙排列返回
]
})
/*
* 查询数据表中的数据总数: 使用数据表的findAndCountAll()方法
* 该方法表示查询数据的同时查询总的数据条数: 返回值的count属性值中便可以获取到总数据条数
* userListAndCount.rows 中的属性值表示的是我们查询获取的数据组成的数组
*/
const userListAndCount = await User.findAndCountAll({
limit: 2,
offset: 2,
order: [
['id', 'desc']
]
})
console.log(
'userListAndCount:',
userListAndCount.count, //所有的总数, 不考虑分页
userListAndCount.rows.map(user => user.dataValues)
)
/**
* 注: 如果我们的数据表中存在外键关联,我们在查询时需要进行连表查询时,可以在findAndCountAll() 的方法中传递进入关联查询的表项: include项: 例:
* const blogListWithUser = await Blog.findAndCountAll({
* order: [
* ['id', 'desc']
* ],
* include: [ // 连表查询
* {
* model: User,
* attributes: ['userName', 'nickName'],
* where: {
* userName: 'zhangsan'
* }
* }
* ]
* })
* 此处我们举了一个blog表外键关联User表连表查询: 表示在查询Blog 表时连带查询出blog 的用户信息
* 连表查询时需要保证我们的两个表之间已经建立了外键关系
*/
- 更新数据操作:
/**
* 使用数据表的 update 方法更新数据表中的数据:
* 参数配置:
* 参数1: 更新的数据内容
* 参数2: 匹配需要进行更新的数据项
*/
!(async function(){
const updateRes = await User.update({
nickName: '张三2',
},{
where: {
userName: 'zhangsan'
}
})
// 函数执行返回一个数组,表示更新的数据条数
console.log(updateRes[0])
})()
8. 删除数据操作:
/**
* 使用数据表的 destroy方法删除掉数据表中的数据:
* 参数: 指定删除数据表中的那些数据的配置对象
*/
!(async function(){
const delUserRes = await User.destroy({
where: {
id: 1
}
})
// 函数执行的返回值为删除的数据条数
console.log(delUserRes)
})()
- 以上我们使用Sequelize 完成操作mysql 数据库执行增删改查 操作就基本实现了,关于之前我们有提到的数据表外键关联, 在Sequelize 中我们如何实现,这里我们也简单说一下:
/**
* 注: 我们创建一个Blog 表和 User 表进行关联
*/
// 外键关联: 默认情况: 创建的关联 关联上的是被关联表的id: 这里使用 belongTo方法
// 将Blog表关联在User表的userId数据项上
Blog.belongsTo(User, {
// 创建外键 Blog.userId -> User.id
foreignKey: 'userId'
})
// 或者使用hasMany() 方法创建外键,该方法仍然表示将Blog表和User表的userId 关联上
User.hasMany(Blog, {
foreignKey: 'userId'
})
- 最后在说一下的就是我们开始时说到的线上版本我们配置连接池的东西:
// 线上环境配置: 创建连接池, 进行连接池的一些基本的配置
conf.pool = {
max: 5, // 连接池中最大的连接数量
min: 0, // 连接池中最小的连接数量
idel: 10000 // 如果一个连接池未被使用, 则释放该连接池... 连接池的释放 时间
}
// 创建 Sequelize 实例连接数据库时我们将该配置项传递给创建的实例即可
这里我们讲到的Sequelize 连接操作数据库的只是些简单的操作,有关更多复杂的操作如果大家感兴趣可以继续去深入学习