項目git地址:https://github.com/BM-laoli/Node_DAO
概述DAO層的封裝
- 首先我們拿JDBC的DAO層來舉例子
DAO(Data Access Object) 是數據訪問層
Action像是服務員,顧客點什么菜,菜上給幾號桌,都是ta的職責;Service是廚師,action送來的菜單上的菜全是ta做的;Dao是廚房的小工,和原材料(通過hibernate操作數據庫)打交道的事情全是ta管。
對象的調用流程:JSP—Action—Service—DAO—Hibernate(某框架)—數據庫。
- 我們來談談Node的DAO層封裝那些事
基於我目前的開發項目的架構,從數據的流轉來看,它類似於下面這個樣子
Model(數據模型)-- Middleware(數據處理中間件) -- Router(路由處理)
這一講我們主要是關注與Model層的處理,既,如果更加簡單更加精確的的把數據查詢出來
一、 關於Node for MYSQL的DAO封裝
基礎的知識,我們這里不講,我們直接考慮如何在項目中使用
-
首先我們npm mysql,這個沒有什么好解釋的
-
開始封裝一個最基礎的通用的數據鏈接類
要在node中操作mysql,一般有如下的事情要做
基礎的使用我就不講了,我們直接用單例模式來進行封裝成一個類
[model/DAO/model.js]
const mysql = require('mysql')
/**
* 數據模型的基類
* 封裝了數據庫操作
*/
module.exports = class Model {
// 連接對象
static conn = null
/**
* 初始化數據連接操作
*/
static connection() {
Model.conn = mysql.createConnection({
host: '127.0.0.1',
user: 'root',
password: '123',
database: 'blog'
})
Model.conn.connect(err => {
if (err) {
console.log(`數據庫連接失敗:${err.message}`)
}
})
}
/**
* 關閉數據庫連接,注意,你需要及時的關閉查詢數據流,比秒消耗性能
*/
static end() {
if (null != Model.conn) {
Model.conn.end()
}
}
/**
* 通用查詢方法
* @param {string} sql 要執行的SQL語句
* @param {Array} params 給SQL語句的占位符,以后由具體的Model決定具體的傳入參數
*/
static query(sql, params = []) {
return new Promise((resolve, reject) => {
this.connection()//調用連接
//開始查詢
Model.conn.query(sql, params, (err, results) => {
if (err) {
reject(err)
} else {
resolve(results)
}
})
//關閉流
this.end()
})
}
}
- 具體的業務查詢的實現
這里我們假設我的表里面有這些字段,我們具體的業務就是在這里構造查詢條件然后就可以去展開具體的查詢了,注意繼承
[model/articel.js]
const Mysql = require('./DAO/model');
//開始實現具體的查詢Model
module.exports = class Article extends Mysql {
/**
* 描述 查詢所有的列表,這里是SQL的具體的實現方法,根據以往需求來處理
* @date 2020-04-29
* @returns {any} 返回值是查詢出來的數據對象
*/
static getList() {
return new Promise((resolve, reject) => {
let sql = 'SELECT id,title,content,`time`,thumbnail FROM article ORDER BY TIME DESC'
this.query(sql).then(results => {//調用父類的查詢方式
resolve(results)
}).catch(err => {
console.log(`獲取文章列表失敗:${err.message}`)
reject(err)
})
})
}
/**
* 獲取指定文章的詳情
* @param {integer} id 文章編號
*/
static getArticleById(id) {
return new Promise((resolve, reject) => {
let sql = 'SELECT a.id,a.title,a.content,a.`time`,a.hits,a.`category_id`,c.`name`,a.`thumbnail`,a.`hot` FROM article a,category c WHERE a.`category_id` = c.`id` AND a.id = ?'
this.query(sql, id).then(results => {//調用父類的查詢方式
resolve(results[0])
}).catch(err => {
console.log(`獲取指定文章的詳情失敗:${err.message}`)
reject(err)
})
})
}
}
然后呢?如何使用?具體的node項目中,需要說明的,以上的兩端代碼 在node中,都是處於Model下的,有了model使用就相對比較簡單了,
router( 調用中間件mideelwear )--- middleware(接受到router的需求開始調用模型層拿數據) --以req方式,丟回給router,router反過來拿數據去渲染或者做成API接口就可以了
[router/index.js]
+++
const Articel = require('../middelwear/article')
+++
articleApp.get('/:id', [Articel.getArticleById], (req, res) => {
let { article } = req//由於我們之前的中間件已經把結果存到了req里面,這樣我們就能直接拿了
//如果是模板渲染可以這樣來干
// res.render('article', { article: article })//如果你需要做API接口於是乎你可以以JSON形式丟出去
res.send( JSON.stringify( { article: article } ) )
})
[middleware/articel.js]
//如果數據是從 路由Router過來
function getArticleById (req, res, next) {
//然后再路由里,我只需要這樣用就行了,直接從req里面解構過來,需要說明一些
// let id = req.params.id,這個用於處理get /:?這樣的數據,?的具體數據,就能從req.params里面弄出來
// let id = req.body,這個用於處理POST這樣的數據,具體數據,就能從req.body里面弄出來
let id = req.params.id
Article.getArticleById(id).then(results => {
req.article = results
next()//放行
}).catch(err => {
next(err)
})
}
以上就是最基礎的Node for Mysql數據的DAO層的封裝,這樣一來,后面的數據操作,就變得簡單的多了,希望我的文章對你有所幫助!~~~
二、關於Node for MangoDB的DAO封裝
-
首先是npm install mongoose下載 不多解釋
-
開始封裝
這里我們同樣也是有兩個層面的模型,一個dao層,一個是具體的實現層
[molde/dao/]
//這里僅僅演示了一部分的dao命令
module.exports = class MongoDB {
//構造器
constructor(collectionName) {
this.MongoClient = require('mongodb').MongoClient;
this.url = "mongodb://root:root@localhost/";
this.dbName = "blogs_2node_kaifa";
//由於我們的表設計到了多表的操作,所以表(集合)是要變來變去的,所以這里改成由具體的實現傳入
//具體的操作是那項表交與用戶具體實現,
this.collection = collectionName;
}
//不要加入static ,如果加入就變成靜態的了,實例的對象就用不了這些靜態的方法了
//鏈接
connect(url,callback){
if (!url) {
return;
}
this.MongoClient.connect(url, function(err, db) {
callback(err, db);
db.close();//關閉流
});
}
/**
* 描述 插入單條數據
* @date 2020-04-29
* @param {any} oneObj
* @param {any} callback
* @returns {any}
*/
insertOne(oneObj, callback) {
let dbName = this.dbName;
let collection = this.collection;
console.log('this.d');
this.connect(this.url, function(err, db) {
var client = db.db(dbName);
client.collection(collection).insertOne(oneObj, function(err, res) {
if (err) throw err;
if (callback) {
callback(err, res);
}
});
});
}
/**
* 描述 增加多條數據
* @date 2020-04-29
* @param {any} objs
* @param {any} callback
* @returns {any}
*/
insertMany(objs, callback) {
if (!Array.isArray(objs)) {
throw new Error("非數組,類型不匹配!");
return;
}
let dbName = this.dbName;
let collection = this.collection;
this.connect(this.url, function(err, db) {
var client = db.db(dbName);
client.collection(collection).insertMany(objs, function(err, res) {
if (err) throw err;
if (callback) {
callback(err, res);
}
});
});
}
/**
* 描述 查詢操作
* @date 2020-04-29
* @param {any} whereStr
* @param {any} callback
* @returns {any}
*/
find (whereStr, callback) {
let dbName = this.dbName;
let collection = this.collection;
this.connect(this.url, function(err, db) {
if (err) throw err;
var client = db.db(dbName);
//開始傳入指定的查詢條件
client.collection(collection).find(whereStr).toArray(function(err, result) {
if (err) throw err;
if (callback) {
callback(err, result);
}
});
});
}
[model/user.js]
//示例話具體的表(集合)操作對象
const MongoDB = require('./02.通用的模型層');
//實例化dao層,並且給它指定的表
setCollection = new MongoDB('setCollection')
module.exports = class User{
static getUser(queryMD){
return new Promise((resolve,reject)=>{
setCollection.insertOne(queryMD,(err,result)=>{
if(result){
resolve(result)
}else{
reject(err)
}
})
})
}
static updataMany(queryMD){
return new Promise((resolve,reject)=>{
setCollection.updataMany(queryMD,(err,result)=>{
if(result){
resolve(result)
}else{
reject(err)
}
})
})
}
}
以上外面的mongoose的模型層就構建好了,接下里就是我們的中間件部分
//這里是模擬的是中間件,。如果這里有傳參和之前的mysql的dao層是一樣的操作直接把req身上的都寫帶下來就可以了
const User = require('./03_具體的模型實現層');
function getSet(queryMD){
//在這里你可以取查詢的要素做處理然后,處理完成之后才丟給查詢
//這里僅僅是為了演示,就不做具體的要素處理了,
console.log('Jigru1');
User.getUser(queryMD).then((result) => {
console.log( result );//這樣我們就查詢成功了
}).catch((err) => {
console.log(err);
});
}
//假設,我現在要設置username=admin的用用戶,於是乎我就
getSet({"username":"admin"})
特別說明:由於mongo中的不能像msq這種直接用sql的查詢,所以使用起來,也不太爽,對於find()之后的各種條件匹配,我們不寫在dao層中,具體的模型實現的時候,在寫具體的模型查詢語句,我認為是極好的一種規范,
歡迎大佬賜教,歡迎大家來我的git讓這個dao層的封裝變得更強大