1. 程式人生 > >Vue2+Koa2+Typescript前後端框架教程--05Sequelize的使用(ORM)

Vue2+Koa2+Typescript前後端框架教程--05Sequelize的使用(ORM)

本篇開始分享Node.js後端服務開發中對於資料結構ORM的實現,主要使用的技術棧是:Sequelize。

上一篇文章中講到班級管理的資料結構:ID,班級名稱,班級編碼,班主任ID,使用的資料庫是MySQL,通過Sequelize,實現簡單的增刪改查的API。

1. MySQL中建立資料庫和班級表。

   1.1 建立資料庫demo_node

CREATE DATABASE `demo_node` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;

   1.2 建立班級表t_class

CREATE TABLE `demo_node`.`t_class` (
  `id` VARCHAR(36) NOT NULL,
  `class_name` VARCHAR(45) NULL,
  `class_code` VARCHAR(20) NULL,
  `head_teacher_id` VARCHAR(45) NULL,
  PRIMARY KEY (`id`))
COMMENT = '班級表';

2. 安裝Sequelize。

npm install sequelize -s
npm install mysql2 -s

注:Sequelize連線哪種資料庫就要安裝對應資料庫的驅動

3. src根目錄下新增資料庫配置檔案:db_config.ts

import { Sequelize } from 'sequelize';


const DbSequelize = new Sequelize({
    host: "localhost",//本地:localhost,其他伺服器使用ip地址
    dialect: "mysql",//連線資料庫型別
    database: "demo_node",//資料庫名稱
    username: "root",//資料庫賬戶使用者名稱
    password: "123456",//資料庫賬戶密碼
    define: {
        timestamps: false,//是否開啟時間戳createAt  deleteAt  updateAt    
        underscored: true,//下劃線 
        freezeTableName: true, //禁止sequelize修改表名,預設會在表後邊新增一個字母`s`表示複數
        paranoid: true //開啟假刪除
    },
    pool: {
        max: 10,
        min: 0,
        acquire: 30000,
        idle: 10000
    },
    timezone: '+08:00',//時區設定,東八區
});

export default DbSequelize;

4. 定義Model:在models資料夾中修改class.ts,定義班級模型。(上一篇使用的是sequelize-typescript,這裡沒有使用,所以模型定義有所區別,但是思路一致)

import { Sequelize, DataTypes } from "sequelize";
import DbSequelize from "../db_config";

//班級模型
export default DbSequelize.define('ClassModel', {
    id: {
        type: DataTypes.STRING,
        primaryKey: true//設為主鍵
    },
    className: {
        type: DataTypes.STRING
    },
    classCode: {
        type: DataTypes.STRING
    },
    headTeacherId: {
        type: DataTypes.STRING
    },
}, {
    tableName: 't_class'//定義對應資料庫表名
});

5. 定義Service,在services中修改class.ts:

import ClassModel from '../models/class';

//班級管理服務
export default class ClassService {
    //獲取所有班級
    async findClassList() {
        try {
            return ClassModel.findAll({
                attributes: ['id', 'className', 'classCode', 'headTeacherId']
            });
        }
        catch (err) {
            throw (err);
        }
    }

    //獲取單個班級
    async findClassById(classId: string) {
        try {
            return ClassModel.findOne({
                attributes: ['id', 'className', 'classCode', 'headTeacherId'],
                where: { id: classId }
            });
        }
        catch (err) {
            throw (err);
        }
    }

    //刪除班級
    async deleteClass(classId: string) {
        try {
            return await ClassModel.destroy({ where: { id: classId } });
        }
        catch (err) {
            throw (err);
        }
    }


    //修改班級
    async editClass(classObj: any) {
        try {
            return await ClassModel.update(classObj, { where: { id: classObj.id }, individualHooks: true });
        }
        catch (err) {
            throw (err);
        }
    }

    //新增班級
    async addClass(classObj: any) {
        try {
            return await ClassModel.create(classObj);
        }
        catch (err) {
            throw (err);
        }
    }
} 

6. 定義Controller,在controllers資料夾中修改班級控制器class.ts:

import ClassService from '../services/class';

const clsService = new ClassService();

//班級管理控制器
export default class ClassController {
    //查詢所有班級
    static async findClassList(ctx: any) {
        try {
            //呼叫查詢列表服務,獲取結果
            let res = await clsService.findClassList();
            ctx.body = {
                status: 1,//返回碼:1操作成功,0操作錯誤
                data: {
                    classList: res
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }

    //根據班級id獲取班級詳細資訊
    static async findClassById(ctx: any) {
        try {
            let id = ctx.request.query.id;
            if (!id) {
                ctx.body = {
                    status: 0
                }
                return;
            }
            //呼叫查詢詳情服務,獲取結果
            let res = await clsService.findClassById(id);
            ctx.body = {
                status: 1,
                data: {
                    class: res
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }

    //刪除班級
    static async deleteClass(ctx: any) {
        try {
            let id: string = ctx.request.body.id;
            //呼叫刪除服務,獲取結果
            let res: any = await clsService.deleteClass(id);
            if (res === 1) {
                ctx.body = {
                    status: 1
                }
            }
            else {
                ctx.body = {
                    status: 0
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }

    //修改班級
    static async editClass(ctx: any) {
        try {
            let obj: any = ctx.request.body;
            //呼叫修改服務,獲取結果
            let res: any = await clsService.editClass(obj);

            if (res[0] !== 1) {
                ctx.body = {
                    status: 0
                }
            }
            else {
                ctx.body = {
                    status: 1,
                    data: {
                        classId: res[1][0].id
                    }
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }

    //新增班級
    static async addClass(ctx: any) {
        try {
            let obj: any = ctx.request.body;
            //呼叫新增服務,獲取結果
            let res: any = await clsService.addClass(obj);

            if (!res) {
                ctx.body = {
                    status: 0
                }
            }
            else {
                ctx.body = {
                    status: 1,
                    data: {
                        classId: res.id
                    }
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }
}

 

7. router如上篇一致,如下:

import KoaRouter from 'koa-router';
import ClassController from './controllers/class';

const router = new KoaRouter();
router.post('/api/class/addClass', ClassController.addClass);
router.post('/api/class/editClass', ClassController.editClass);
router.post('/api/class/deleteClass', ClassController.deleteClass);
router.get('/api/class/findClassById', ClassController.findClassById);
router.get('/api/class/findClassList', ClassController.findClassList);

export default router;

8.開始測試:

 8.1 安裝koa-body: 由於新增修改刪除定義為post方法,所以首先要安裝koa-body,才能獲取到post過來的資料(刪除也可以使用get)

npm install koa-body -s

 8.2 修改app.ts,新增koa-body中介軟體引用

const Koa = require('koa');
import KoaBody from "koa-body";

const app = new Koa();

app.use(KoaBody({
  multipart: true,
  formidable: {
      maxFileSize: 1000 * 1024 * 1024    // 設定上傳檔案大小最大限制,預設2M
  },
  formLimit: "10mb",
  jsonLimit: "10mb",
  textLimit: "10mb"
}));

//引入路由
import router from './router';
//新增中介軟體
app.use(router.routes());
app.use(router.allowedMethods());

app.use(async (ctx: any) => {
  ctx.body = 'Hello World...Hello LaoLv';
});

console.log('app server start on port 3000...')
app.listen(3000);

8.3 新增班級,使用postman,操作如下:

  資料庫表展示如下:

 8.4 更新班級,操作如下:

  

  資料庫表展示如下:

 

 

  8.5 查詢班級,操作如下:

 

  8.6 刪除班級,操作如下:

 

   資料庫表展示如下:

9. 如上所示,使用sequelize簡單實現三層模式對班級的增刪改查。檔案結構圖如上篇一致:

 

這樣,基礎的增刪改查資料流向基本完成。後面會對sequelize中複雜查詢進行詳細分享,敬請期待。

(文章為老呂原創,轉載請註明出處)

&nbs