一、安装sequelize和初始化
sequelize为ORM的一种框架,ORM全称为:Object Relational Mapping,意思是对象关系映射,使用这个框架,你就不要用繁杂的sql语句去操作数据库了,直接用对象关系去创建数据库
中文官网:https://www.sequelize.com.cn/core-concepts/model-querying-finders
首先安装sequelize:npm install sequelize -S
再安装sequelize的脚手架,就像vue和vue-cli一样:npm install sequelize-cli -S
然后在初始化,一定要用npx命令:npx sequelize-cli init
为什么使用npx而不是npm:
npm是Node.js的软件包管理器,其目标是自动化的依赖性和软件包管理。,而npx是与npm捆绑在一起的另一个安装工具,npx 会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你安装!首先依赖已经在npm处安装完成了,而下面的初始化和创建模块的命令只需要去安装包里面找就行了
安装完后,项目就会新增这几个文件:
config文件:配置生产和开发环境的需要连接的数据库名称,地址,账户密码等等
migrations文件:和开发环境和生产环境的数据库迁移相关
models文件:每一个models和数据表关联的文件
seeders:数据表的初始化脚本
连接开发、测试、生产环境的数据库,在config中连接你所在的数据库,包括用户名,密码,数据库名。地址,数据库类型
二、创建ORM模型
下面代码命令的意思就是:创建一个sequelize的模型,模型名称为:User,有一个name属性,创建完后就会发现migrations和models文件夹下面多了一个文件,
migrations下文件:下面为模型生产的代码:主要描述了模型有哪些创建的字段和默认的字段,各个属性的类型等等
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Users');
}
};
models文件夹下生成的文件:
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
User.init({
name: DataTypes.STRING
}, {
sequelize,
modelName: 'User',
});
return User;
};
三、创建表
第一步要先创建数据库驱动,mysql数据库在nodejs中提供的驱动就叫:mysql2,要先安装驱动,然后再创建表,以为在开发环境创建数据表,创建完后下面就提示创建成功,表名为user,再用navicat查看发现多了一张user的表
四、创建接口,操作数据库数据
主要代码如下:引入模型,三个接口:新增数据、查询数据、根据id去查询数据,写完后就可以在postman中测试一下
// 引入ORM模型
const models = require('../models')
// models.use
// modelse.Sequelize
// models.sequelize
// node-application---ORM(sequelize)--驱动(nodejs的mysql驱动)-mysql db
// ORM模型
// 创建表,传入一个参数name
app.get('/create',async (req,res) => {
let {name} = req.query
// models返回的是一个和sequelize相关的promise对象
let user = await models.User.create({
name
})
console.log(user)
res.json({
mesg: '创建成功',
user
})
})
// 查询user列表
app.get('/list',async (req,res) => {
let list = await models.User.findAll()
res.json({
list
})
})
// 根据id去查询数据
app.get('/detail/:id',async (req,res) => {
let {id} = req.params
let user = await models.User.findOne({
where:{id}
})
// 返回请求的数据
res.json({
user
})
})
index.js完整文件
const express = require('express')
const userrouter = require('./router/demo')
const app = express()
// 引入ORM模型
const models = require('../models')
// models.use
// modelse.Sequelize
// models.sequelize
// node-application---ORM(sequelize)--驱动(nodejs的mysql驱动)-mysql db
// ORM模型
// 创建表,传入一个参数name
app.get('/create',async (req,res) => {
let {name} = req.query
// models返回的是一个和sequelize相关的promise对象
let user = await models.User.create({
name
})
console.log(user)
res.json({
mesg: '创建成功',
user
})
})
// 查询user列表
app.get('/list',async (req,res) => {
let list = await models.User.findAll()
res.json({
list
})
})
// 根据id去查询数据
app.get('/detail/:id',async (req,res) => {
let {id} = req.params
let user = await models.User.findOne({
where:{id}
})
// 返回请求的数据
res.json({
user
})
})
// 路由
// router:get/post/put/delet...
app.get('/test', (req,res) => {
res.json({
mesg: 'test'
})
})
app.get('/test', (req,res) => {
res.json({
mesg: 'test'
})
})
app.all('/demo', (req,res) => {
res.json({
mesg: 'demo',
method: req.method
})
})
// 中间件:处理整个流程拦截中间某一个过程的函数
function demo_middleware(err, req,res,next) {
// 处理异常
// 处理业务功能,转交控制权,next
// 响应请求,->结束请求->当做路由的处理函数
// 使用场景:
// APP级别的:顶级地方注册(如该文件,项目的启动文件)
// router级别的:子路由中定义的
// 异常处理
}
// 要发送请求才会执行
function test(req,res,next) {
console.log('请求来了')
next()
}
app.use(test)
// 子路由:调用的子路由地址,使用路由,可加入父级路径,命名空间,如下的/user,如果该处调用的路由路径和APP级别路由路径一样,则会只调用APP级别路由
app.use('/user',userrouter)
app.use(express.static('static', {
// 不带后缀的请求默认设置一些后缀
extensions:['html', 'htm']
}))
// 定义中间件,在所有路由中使用
// function middle(req,res,next) {
// let {name} = req.query
// if (!name || !name.length) {
// res.json({
// mesg:'缺少参数'
// })
// }else {
// next()
// }
// }
// app.all('*',middle)
// 异常处理,中间件的方式实现
// 定义一个异常
app.get('/err',(req,res) => {
// throw new Error('服务器异常')
res.json({
mesg
})
})
function error_handle(err,req,res,next) {
if (err) {
res.status(500).json({
mesg: '服务器异常'
})
}
}
// 异常处理的注册放在所有路由最底部,404在express中并不是一个异常,
// 所以没有err对象,用中间件单独处理,当前面路由都没法匹配时,由404中间去处理
app.use(error_handle)
function not_found(req,res,next) {
res.json({
mesg: 'api不存在'
})
}
app.use(not_found)
app.listen(3000, () => {
console.log('服务启动')
})
测试:
这样一个完整的开发流程就走完了,写了一个简单可供前端调用接口的服务端。流程为:
前端view——ajax/axios请求接口——node.js程序(express)——ORM对象关系模型处理nodejs与数据库之间的连接调用关系(sequelize)——数据库驱动(nodejs提供的mysql2驱动)——数据库(mysql db)
五、使用数据库的两种方法
1、在express中操作数据库的第一种方法就是,如上面介绍的,使用sequelize框架
2、第二种方式就是直接使用sql语句操作数据库,这两种方法可以同时使用,具体使用方法如下:
(1)安装数据库,:npm install mysql -S
注意:这次是安装数据库模块,上面安装的mysql2是mysql数据库的驱动
(2)在入口文件index.js中引入、使用
// 连接mysql数据库
const mysql = require("mysql")
// 定义连接数据库的对象
const db = mysql.createConnection({
host:"localhost",
user:"root",
password:"root",
database:"db3"
})
// 连接数据库
db.connect((err) => {
if (err) {throw err}
console.log('连接成功')
})
app.get('/task',(req,res) => {
// 使用查询的sql语句
let sql = "SELECT * FROM tasks"
// 调用sql语句,并且返回值
db.query(sql, (err, result) => {
if (err) {
console.log(err)
} else {
res.json({
mesg:"获取数据成功",
data:result
})
// 不能再次发送响应
// res.send("获取tasks表数据成功")
}
})
})
(3)分模块使用sql语句
在实际项目中,不可能所欲接口都放在入口文件中,所以一定需要分模块,所以我们定义一个mysql.js放链接mysql的配置,然后在分路由模块task.js中定义接口
mysql.js:
// 连接mysql数据库
const mysql = require("mysql")
// 定义连接数据库的对象
const db = mysql.createConnection({
host:"localhost",
user:"root",
password:"root",
database:"db3"
})
module.exports = db
task.js:
const express = require('express')
// 与入口文件的app对象在路由这块是有相同的API
const router = express.Router()
// 引入ORM模型models下的index.js文件
const models = require('../../models')
// 使用mysql语句操作数据库
const db = require('../mysql')
// 使用sequelize框架:新增数据,传入一个参数name,content,status
router.get('/create',async (req,res) => {
let {name,content,status} = req.query
// models返回的是一个和sequelize相关的promise对象
let user = await models.Task.create({
name,
content,
status
})
console.log(user)
res.json({
mesg: '创建成功',
user
})
})
// 使用sql语句新增数据
router.get('/task/createTask',(req,res) => {
let {name,content,status,createdAt,updatedAt} = req.query
// 新增的sql语句
let sql = `INSERT INTO tasks (name,content,status,createdAt,updatedAt) VALUES ('${name}','${content}','${status}','${createdAt}','${updatedAt}')`
// 调用sql语句,并且返回值
db.query(sql, (err, result) => {
if (err) {
console.log(err)
} else {
res.json({
mesg:"新增数据成功"
})
}
})
})
module.exports = router
文件结构: