orm的方式:
數據表使用js的模型 (class或者對象) 來代替
一條或多條記錄,用js的一個對象或者數組替代
sql語句用對象的方法代替。
拋開後臺項目,新建文件夾sequelize-test
npm init -y
npm i mysql2 sequelize -d
查看package.json
"dependencies": {
"mysql2": "^2.0.2",
"sequelize": "^5.21.2"
}
ps: 參考https://www.npmjs.com/package/mysql2
,思考在不使用orm工具時候如何連接數據庫,如何操作數據庫。
git config --global core.autocrlf false 可以解決一個報錯
新建src
文件夾下新建文件seq.js
參考getting-started
創建sequelize模型,連接數據庫
const Sequelize = require('sequelize');
const conf = {
host: 'localhost',
dialect: 'mysql'
}
const seq = new Sequelize('flyingfish_db', 'root', '950210zsrtxdy', conf)
module.exports = seq
// 接下來就可以使用這個實例進行模型創建以及查詢等操作
測試連接,註釋掉module.exports = seq
在seq.js文件夾下方添加如下代碼
seq
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
運行src/seq.js
創建模型
新建model.js
const Sequelize = require('sequelize')
const seq = require('./seq.js')
// 創建 User 模型,雖然下面是user,但是數據表的名字會變成users
const User = seq.define('user', {
// id會自動創建並設爲主鍵,並且自增
userName: {
type: Sequelize.STRING, //varchar(255)
allowNull: false //不能爲空
},
password: {
type: Sequelize.STRING,
allowNull: false
},
nickName: {
type: Sequelize.STRING,
comment:'暱稱'
// allowNull defaults to true
}
// 自動創建createdAt和updatedAt
}, {
// options
});
module.exports = { User }
新建sync.js
const seq = require('./seq.js')
require('./model.js')
// 3 測試連接
seq.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
// 4 執行同步
seq.sync({force: true}).then(()=>{
console.log('sync ok')
process.exit() //不退出sequelize會一直佔用進程
})
自動生成的
在添加comment之後。
接着創建blog
const Blog = seq.define('blog', {
title: {
type: Sequelize.STRING,
allowNull: false
},
content: {
type: Sequelize.TEXT,
allowNull: false
},
userId: {
type: Sequelize.INTEGER,
allowNull: false
},
})
輸出
module.exports = { User, Blog }
總結: 連接數據庫 —— 創建數據模型 —— 測試連接 ——執行同步
創建外鍵的代碼
在model.js裏
// 外鍵關聯
Blog.belongsTo(User,{
// 創建外鍵 Blog.userId -> User.id 是一個多對一的關係。
foreignKey: 'userId'
})
還有Blog.belongsTo(User)
這種寫法,
我們需要把之前創建Blog模型的userId
這一項給去掉,其實User的id還有Blog的userId都可以自動生成的。(這種寫法並不推薦,不明顯)
創建外鍵的兩種用法
// 外鍵關聯
Blog.belongsTo(User,{
// 創建外鍵 Blog.userId -> User.id 是一個多對一的關係。
foreignKey: 'userId'
})
// 創建外鍵的另一種方式
User.hasMany(Blog,{
// 創建外鍵 Blog.userId -> User.id 是一個一對多的關係。
foreignKey: 'userId'
})
爲什麼要兩個一起寫呢?因爲可以誰在前面誰就可以優先索引。
測試
這裏有一個問題就是爲什麼從users裏面看不到外鍵,而從blogs裏面可以看得到?
畫一下ER圖,navicat怎麼畫ER圖?
選擇report 然後點擊右下角的
就可以看到ER圖:
怎麼導出爲pdf以後再想吧。
插入數據
新建create.js文件
IO操作是異步操作,使用async和await
// insert 語句
const { Blog, User } = require('./model.js')
// ! 表示忽略之前的出現錯誤,隔開下面的代碼,是自保的一種方法。
!(async function(){
// 創建用戶,通過create的方式插入一條新的數據
const zhangsan = await User.create({
userName: 'zhangsan',
password: '123',
nickName: '張三'
})
console.log('zhangsan: ',zhangsan.dataValues)
console.log('zhangsanId: ',zhangsan.dataValues.id)
const lisi = await User.create({
userName: 'lisi',
password: '123',
nickName: '李四'
})
console.log('lisiId: ',lisi.dataValues.id)
const blog1 = await Blog.create({
title:'標題1',
content:'內容1',
userId:zhangsan.dataValues.id
})
const blog2 = await Blog.create({
title:'標題2',
content:'內容2',
userId:lisi.dataValues.id
})
const blog3 = await Blog.create({
title:'標題3',
content:'內容3',
userId:lisi.dataValues.id
})
console.log('blog1: ',blog1.dataValues)
console.log('blog2: ',blog2.dataValues)
console.log('blog3: ',blog3.dataValues)
})()
查詢數據
新建一個select.js
查詢單條數據
const { User, Blog } =require('./model.js')
!(async function(){
// 查詢一條記錄
const zhangsan = await User.findOne({
where:{
userName:'zhangsan'
}
})
console.log('zhangsan:',zhangsan.dataValues)
// 查詢特定的列項
const zhangsanColumns = await User.findOne({
attributes: ['userName','nickName'],
where:{
userName:'zhangsan'
}
})
console.log('zhangsanColumns:', zhangsanColumns.dataValues)
})()
查詢一個列表
const zhangsanBlogList = await Blog.findAll({
where:{
userId:2
},
order:[
['id','desc']
]
})
想想怎麼輸出這個zhangsanBlogList
zhangsanBlogList.forEach(item=>{
console.log(item.dataValues)
})
還有這種
console.log('zhangsanBlogList :', zhangsanBlogList.map(blog=>
blog.dataValues
))
map後面是怎麼寫的。
分頁
const zhangsanBlogList = await Blog.findAll({
limit:2,
offset:0,
where:{
userId:2
},
order:[
['id','desc']
]
})
console.log('zhangsanBlogList :', zhangsanBlogList.map(blog=>
blog.dataValues
))
查詢總數
const blogListAndCount = await Blog.findAndCountAll({
limit:2,
offset:0,
order:[
['id','desc']
]
})
console.log(blogListAndCount.count,
blogListAndCount.rows.map(blog=>blog.dataValues))
連表查詢依賴於之前做的外鍵關聯
爲什麼外鍵關聯要兩個一起寫?
連表查詢1
// 需要找出blog列表,而且每一條需要包含作者的名字和暱稱
const blogListWithUser = await Blog.findAndCountAll({
order:[
['id','desc']
],
include:[{
model:User,
attributes:['userName','nickName'],
where:{
id:2
}
}]
})
console.log(blogListWithUser.count,
blogListWithUser.rows.map(blog=>{
const blogVal = blog.dataValues;
const userVal = blogVal.user.dataValues;
blogVal.user = userVal
return blogVal
}))
連表查詢2
每個博客對應一個用戶,一個用戶對應多個博客,從用戶表做索引的話
更新
更新用戶暱稱
這個是返回結果
如果這個修改元素的第一個數大於0就是修改成功了。
刪除一個用戶的話也會把他對應的文章給刪除掉,因爲已經做了外鍵關聯了,他們之間有刪除的關係
因爲外鍵不是我們自己建的,它會自動的restrict模式,不一定能夠刪除成功
所以我們試着刪一下,不成功可以再改
刪除更新遇到問題如果是跟外鍵有關,就可以去可視化操作界面
連接池:
問:什麼是連接池? 連接池是數據庫本身的機制,連接池本身存在在內存或進程中提供了很多現成的連接
問:線上環境怎麼實現連接池(pool),其中的max和min的參數的意義?idle參數的意思?如果一個連接池多長時間內沒有被使用,被釋放
conf.pool = {
max:5,
min:0,
idle:10000 //10s
}
問:怎麼判斷線上環境還是線下環境?