1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 记录nodejs使用express搭建一个api服务器程序(5)-nodejs操作SQL数据库 Sequelize和Knex

记录nodejs使用express搭建一个api服务器程序(5)-nodejs操作SQL数据库 Sequelize和Knex

时间:2019-04-04 12:34:16

相关推荐

记录nodejs使用express搭建一个api服务器程序(5)-nodejs操作SQL数据库 Sequelize和Knex

此文章是我自己用来记录如何搭建一个以express为基础的api服务器框架的过程,并不是什么新手教程,并不会每一步都写得非常详细,如果您要阅读此文,需要一点nodejs和编写代码的基础知识

文接上篇 链接: 地址 /goodboy31985/article/details/106260004

在上文基础上,修改和完善api服务器的框架

nodejs操作SQL数据库,Sequelize和Knex

安装mysql数据库的npm包直接使用sql语句操作数据库Knex使用通过浏览器查询用户信息Sequelize使用

安装mysql数据库的npm包

要在本机安装mysql数据库,推荐使用docker,具体内容可以参考之前的文章

链接: link /goodboy31985/article/details/106204527

无论你选择是否使用Sequelize或者Knex等其他更方便的工具,为了让nodejs能够操作mysql,需要安装mysql包,直接使用npm安装即可

npm install --save mysql2

安装完成后,我们就已经可以再nodejs中连接并操作数据库了

直接使用sql语句操作数据库

我们先在数据库中创建一个新的数据库test 并新建一张表 palyer,里面填写一些数据

字段包括 id name age phone

并且有2条数据

在项目中新建一个DBManager的文件,创建一个数据库管理类,来管理数据库的操作

DBManager.ts文件内容

// lib/common/DBManager.tsimport mysql2 from "mysql2"export class DBManager{//单例private static instance: DBManager = null;private constructor(){}public static GetInstance(){if (DBManager.instance == null){DBManager.instance = new DBManager();}return DBManager.instance;}//mysql数据库对象sqldb = null;//连接数据库,参数中填写数据库地址,端口等信息InitMysql(){this.sqldb = mysql2.createConnection({host: 'localhost',user: 'root',password: '123456',port: '3306',database: 'test'});}}

在start.ts中写一些测试代码,测试是否能够查询成功

async function main(){//日志增强功能初始化LogHelper.Init();console.log("app start");//ApiServer.GetInstance().Init();//await ApiServer.GetInstance().Run();//mysql测试DBManager.GetInstance().InitMysql()DBManager.GetInstance().sqldb.connect();//连接数据库DBManager.GetInstance().sqldb.query("SELECT * FROM player", (error, results, fields) =>{//如果查询出现错误if (error) {console.error(error);DBManager.GetInstance().sqldb.end();//关闭连接}//打印查询的结果console.log(results);DBManager.GetInstance().sqldb.end();//关闭连接});}main();

我们直接运行一下代码

我们已经可以查询到数据库中相关的内容

这里我们直接使用SQL查询语句

当要执行比较复杂的数据库操作时,直接使用SQL语句显然是比较麻烦的,通常在项目中也很少会这样直接使用,下面就介绍两个比较常用的库,来简化我们的SQL操作

Knex使用

Knex是一款query builder(查询构建器),让我们可以使用nodejs风格的语句来进行SQL操作,很大程度上避免了直接使用SQL语句

直接使用npm进行安装

npm install --save knex

npm install --save mysql2 //knex的功能同样依赖于nodejs的mysql库,如果你在前面已经安装过,这步就可以跳过

修改DBManager.ts文件,引入knex,并使用knex建立连接

// lib/common/DBManager.tsimport knex from "knex"export class DBManager{//单例private static instance: DBManager = null;private constructor(){}public static GetInstance(){if (DBManager.instance == null){DBManager.instance = new DBManager();}return DBManager.instance;}//mysql数据库对象sqldb = null;//连接数据库,参数中填写数据库地址,端口等信息InitMysql(){this.sqldb = knex({client: 'mysql2',//指明数据库类型,还可以是pg,sqlite3等等connection: {//指明连接参数host: 'localhost',user: 'root',password: '123456',port: 3306,database: 'test'},debug: true, //指明是否开启debug模式,默认为true表示开启pool: {//指明数据库连接池的大小,默认为{min: 2, max: 10}min: 2,max: 10,},acquireConnectionTimeout: 10000, //指明连接计时器超时,默认为60000ms});}}export const db=DBManager.GetInstance()//直接导出一个db 代码写起来方便一点

使用了Knex之后,我们基本可以不用考虑查询后连接的关闭问题,它默认是帮我们启用连接池的

这里我们修改一下start.ts中的查询语句

async function main(){//日志增强功能初始化LogHelper.Init();console.log("app start");//ApiServer.GetInstance().Init();//await ApiServer.GetInstance().Run();//mysql测试db.InitMysql()let result = await db.sqldb.select().from("player");console.log(result);console.log(result[0]);console.log(result[0].name);result = await db.sqldb.select("name").from("player").where("id", ">", 1)console.log(result);}main();

代码中执行了2次查询,2个红框分别是2次查询的结果

并且可以直接使用 async 和 await 这样的特性,方便我们写异步代码,脱离回调地狱

通过浏览器查询用户信息

接下来,我们重新调整一下代码,使用浏览器向服务器发送请求,查询用户信息

使用 api/users/:id 这个路径,通过向服务器发送id,获取用户信息

修改start.ts

//start.tsimport fs from "fs"import json5 from "json5";import path from 'path'import {ApiServer } from "./ApiServer/ApiServer";import {LogHelper } from "./lib/common/LogHelper";import {DBManager, db } from "./lib/common/DBManager";//项目根目录export const rootDir = __dirname + "/";//加载配置文件//读取json5文件内容let jsonFile = fs.readFileSync(path.join(rootDir, "config.json5")).toString();//解析为json文件,并作为模块输出export let config = json5.parse(jsonFile);async function main(){//日志增强功能初始化LogHelper.Init();console.log("app start");//数据库连接初始化db.InitMysql();ApiServer.GetInstance().Init();await ApiServer.GetInstance().Run();}main();

修改UserController.ts

// Controller/UserController.tsimport {Request, Response, NextFunction } from 'express'import {db } from '../lib/common/DBManager';export class UserController{// GET users/:idstatic async UserInfo(req: Request, res: Response,next:NextFunction){let user = req.params;console.log("receive a GET request");console.log('[', req.method, '][', req.originalUrl, ']');console.log(req.params);let userinfo=await db.sqldb.select().from("player").where("id", "=", req.params.id);return res.json(userinfo).end();}}

启动服务器,并且通过浏览器查询用户信息

Sequelize使用

knex还是比较偏向底层的,方便我们构造出响应的sql语句

通常还会使用ORM框架,来操作数据库

关系型数据库每张表有不同的字段,

| id | name | birth |

| 1 | Gaffey | -07-07 |

| 2 | Odie | -08-08 |

每一行数据就可以对应到一个js对象

{"id": 1,"name": "Gaffey","birth": "-07-07"}

这就是传说中的ORM技术:Object-Relational Mapping,把关系数据库的表结构映射到对象上。

我们选择Node的ORM框架Sequelize来操作数据库。这样,我们读写的都是JavaScript对象,Sequelize帮我们把对象变成数据库中的行。

数据库中设计一个user表,来记录用户信息

表中设计以上的字段,用来定义一个用户定义user的模型(Model)

Sequelize通过定义模型,把数据库表中的字段和js对象形成对应的关系

在src下建立Model文件夹,用来存放所有的Model文件,然后新建一个UserModel.ts文件,建立Users的模型

通过npm命令 安装sequelize,同时 还需要安装相应数据库的包比如 mysql

npm install --save sequelize

npm install --save mysql2 //功能同样依赖于nodejs的mysql库,如果你在前面已经安装过,这步就可以跳过

UserModel.ts文件内容

// Model/UserModel.tsimport {Sequelize, Model, DataTypes, BuildOptions } from 'sequelize';import {HasManyGetAssociationsMixin, HasManyAddAssociationMixin, HasManyHasAssociationMixin, Association, HasManyCountAssociationsMixin, HasManyCreateAssociationMixin } from 'sequelize';import {db } from '../lib/common/DBManager.sequelize';//下面的UserModel.init代码需要用到一个sequelize的实例,这里的实例是从DBManager获取的,详解DBManager.sequelize.ts文件db.InitMysql();let sequelize = db.sequelize;export class UserModel extends Model{public id!: number;// 注意在严格模式下需要 `null assertion` 或 `!`. public email!: string;public password!: string;public phone!: string | null;//可以为空的字段public username!: string|null;public nickname!: string|null;public age!: number|null;}UserModel.init({id: {type: DataTypes.BIGINT({length:10}).UNSIGNED,autoIncrement: true,primaryKey:true,},email: {type: DataTypes.STRING(100),allowNull:false,},password: {type: DataTypes.STRING(32),allowNull:false,},phone: {type: DataTypes.STRING(15),allowNull: true,},username: {type: DataTypes.STRING(30),allowNull: true,},nickname: {type: DataTypes.STRING(30),allowNull: true,},age: {type: DataTypes.INTEGER({length:3}),allowNull: true,}},{// 将自动设置所有属性的字段参数为下划线命名方式.// 不会覆盖已经定义的字段选项underscored: true,// 不添加时间戳属性 (updatedAt, createdAt)timestamps: false,// 不删除数据库条目,但将新添加的属性deletedAt设置为当前日期(删除完成时). // paranoid 只有在启用时间戳时才能工作paranoid: false,// 禁用修改表名; 默认情况下,sequelize将自动将所有传递的模型名称(define的第一个参数)转换为复数. 如果你不想这样,请设置以下内容freezeTableName: true,// 定义表的名称tableName: "users",sequelize,})

创建一个DBManager.sequelize.ts文件,用来作为sequelize的管理,为了区别前一部分Knex的内容,我们把原来Knex的管理改名为 DBManager.knex.ts

DBManager.sequelize.ts文件内容

// lib/common/DBManager.sequelize.tsimport {Sequelize } from 'sequelize';import {config } from '../../start';export class DBManager{//单例private static instance: DBManager = null;private constructor(){}public static GetInstance(){if (DBManager.instance == null){DBManager.instance = new DBManager();}return DBManager.instance;}//连接数据库,参数中填写数据库地址,端口等信息sequelize: Sequelize = null;InitMysql(){if (this.sequelize != null){console.log("already inited");return;}this.sequelize = new Sequelize(config.database.dbname,config.database.user,config.database.password,{host: config.database.server,dialect: "mysql",pool: {min: 0,max: 10,idle: 30000,},// disable logging; default: console.loglogging: false})}}export const db = DBManager.GetInstance()//直接导出一个db 代码写起来方便一点

修改start.ts 文件,做一些简单的测试

start.ts

//start.tsimport fs from "fs"import json5 from "json5";import path from 'path'//项目根目录export const rootDir = __dirname + "/";//加载配置文件//读取json5文件内容let jsonFile = fs.readFileSync(path.join(rootDir, "config.json5")).toString();//解析为json文件,并作为模块输出export let config: ConfigInterface = json5.parse(jsonFile);import {ApiServer } from "./ApiServer/ApiServer";import {LogHelper } from "./lib/common/LogHelper";//import { db } from "./lib/common/DBManager.knex";import {cache } from "./lib/common/CacheManager";import {ConfigInterface } from "./Interface/ConfigInterface"import {db } from "./lib/common/DBManager.sequelize";import {UserModel} from "./Model/UserModel"import md5 from "md5"async function main(){//日志增强功能初始化LogHelper.Init();console.info("app start");//数据库连接初始化try{db.InitMysql()//初始化sequelize对象await db.sequelize.authenticate();//进行数据库测试连接console.info('MySQL Connection has been established successfully.');//如果连接成功就打印信息} catch (err) {console.error('Unable to connect to the database:', err);}//进行数据库同步,如果发现数据库中没有这张表,会自动按照Model设置的字段创建数据表,如果已经有表格了,就不做改变await UserModel.sync();//尝试创建一个新用户let newUser = await UserModel.create({email: "test@",password: md5("123456"),//密码保存为MD5形式})console.log(newUser);//查询表格let users = await UserModel.findAll();console.log(users[0].email);ApiServer.GetInstance().Init();await ApiServer.GetInstance().Run();}main();

运行后数据库中就会多出一张users表格,并且我们在里面插入了一行数据

一次最简单的Sequelize数据库操作遍完成了

使用Sequelize可以将数据表映射为对象,操作起来比单纯写SQL语句要方便得多,并且可以自动创建数据表,十分方便

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。