本篇开始分享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中复杂查询进行详细分享,敬请期待。

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;

Vue2+Koa2+Typescript前后端框架教程--05Sequelize的使用(ORM)的更多相关文章

  1. Vue2+Koa2+Typescript前后端框架教程--03后端路由和三层模式配置

    昨天将Koa2的基础框架和自动编译调试重启服务完成,今天开始配置路由和搭建基础的三层架构模式. 路由中间件:koa-router,即路由导航,就是我们平时使用最广泛的get/post方法执行的URL路 ...

  2. Vue2+Koa2+Typescript前后端框架教程--04班级管理示例(路由调用控制器)

    上篇文章分享了简单的三层模式和基础文件夹的创建,本篇将以示例的形式详细具体的展示Router.Controller.Service.Model之间业务处理和数据传输. 1. 班级管理数据模型创建.数据 ...

  3. 快速web开发中的前后端框架选型最佳实践

    这个最佳实践是我目前人在做的一个站点,主要功能: oauth登录 发布文章(我称为"片段"),片段可以自定义一些和内容有关的指标,如“文中人物:12”.支持自定义排版.插图.建立相 ...

  4. com.panie 项目开发随笔_前后端框架考虑(2016.12.8)

    (一) 近日和一同学联系,说了我想要做一个网站的打算.她很感兴趣.于是我们协商了下,便觉得一起合作.她写前端,我写后台.因为我对于前端样式设计并不怎么熟悉. (二) 我们决定先做一个 个人博客. 网上 ...

  5. VSCode 完美整合前后端框架(angular2+.NET core)

    首先打开命令行查看本地.NET版本. 通过命令行安装模板. dotnet new --install Microsoft.AspNetCore.SpaTemplates::* 创建demo目录,并用v ...

  6. web前后端框架整理

    nodejs <——> Express <———> bootstrap <———> angularJS <————> jquery <—————& ...

  7. centos7+宝塔+ssrpanel v3 魔改版 前后端配置教程

    一.服务端 1.安装宝塔 登录 SSH 后,直接安装宝塔. yum install -y wget && wget -O install.sh http://download.bt.c ...

  8. vue2.0 axios前后端数据处理

    目前主流的 Vue 项目,都选择 axios 来完成 ajax 请求,而大型项目都会使用 Vuex 来管理数据. 前言: 使用 cnpm 安装 axios cnpm install axios -S ...

  9. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史

    ---新内容开始--- 番外 大家周一好呀,又是元气满满的一个周一呀!感谢大家在周一这个着急改Bug的黄金时期,抽出时间来看我的博文哈哈哈,时间真快,已经到第十四篇博文了,也很顺顺(跌跌)利利 (撞撞 ...

随机推荐

  1. Leetcode学习笔记(4)

    题目1 ID121 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股 ...

  2. 实验吧bypass the upload

    题目链接: http://ctf5.shiyanbar.com/web/upload 打开提米链接上传一个php文件提示: 按照题目要求上传符合标准的图片提示要上传php文件,明显需要进行上传绕过 经 ...

  3. 使用eslint将项目中的代码修改统一的缩进

    背景 继承了组里师兄师姐写的项目的前端代码,但是是两个人写的,有两格缩进的,有四格缩进的,有字符串外用单引号的,有用双引号的. 于是搜索了一下,可以用eslint强制转化. eslint在github ...

  4. css3(::before)伪元素的使用

    1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset=" ...

  5. 题解-CF1418G Three Occurrences

    题面 CF1418G Three Occurrences 给一个 \(n\) 个数的序列 \(a_i\),求每个出现过的数出现次数为 \(3\) 的子序列个数. 数据范围:\(1\le n\le 5\ ...

  6. AcWing 294. 计算重复

    暴力 其实这题的暴力就是个模拟.暴力扫一遍 \(conn(s_1, n_1)\),若出现了 \(res\) 个 \(s_2\). 答案就是 \(\lfloor res / n1 \rfloor\). ...

  7. C++模板元编程----选择排序

    目录 目录 前言 代码详解 数据的结构 数据的操作 分割向量 合并向量 寻找最大值 排序 总结 前言 模板在C++一直是比较神秘的存在.STL和Boost中都有大量运用模板,但是对于普通的程序员来说, ...

  8. ThreadX——IPC应用之信号量

    一.应用简介 在RTOS的应用开发中,信号量也是经常使用到的一种用于多任务之间信息同步.资源互斥访问的一种手段,常用于协调多个任务访问同一资源的场景.信号量又分为计数信号量和互斥信号量.计数信号量可以 ...

  9. I/O-基本概念

    目录 演变过程 I/O系统基本组成 I/O接口 I/O方式简介 小结 演变过程 I/O系统基本组成 分成软件和硬件 I/O接口 接口可以看作是两个部件之间的交接部分 I/O方式简介 小结

  10. RMAN迁移数据库(不改变文件目录)

    1.目标库创建相应目录mkdir -p /u01/app/oracle/oradata/orclmkdir -p /u01/app/oracle/fast_recovery_area/ORCLmkdi ...