文章目錄
- ORM框架
- Sequelize模塊
- Sequelize的基本使用
- 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資料庫操作 (上)(操作MySQL資料庫及 資料庫連接池)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/295675.html
標籤:其他
