引言

nodejs 开发框架有很多种,比如ExpressKoa, Egg,它们之间又有什么关系,关联呢?

可以这么说,Express是爷爷,那Koa就是儿子,而Egg就是孙子,当然这里并不是说它们的能力,而是说它们的来历。

Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法。

egg.js是阿里旗下的一个基于nodejskoa2的企业级应用框架,基于es6,es7 和nodejs,是『约定优先于配置』的一个 Node.js web 框架
Egg 奉行『约定优于配置』,按照一套统一的约定进行应用开发,团队内部采用这种方式可以减少开发人员的学习成本,开发人员不再是『钉子』,可以流动起来。没有约定的团队,沟通成本是非常高的,比如有人会按目录分栈而其他人按目录分功能,开发者认知不一致很容易犯错。但约定不等于扩展性差,相反 Egg 有很高的扩展性,可以按照团队的约定定制框架。使用 Loader 可以让框架根据不同环境定义默认配置,还可以覆盖 Egg 的默认约定。

到这里大家应该都明白它们之间的关系了,但是它们之间又有什么区别呢?

一句话总结: koaexpress,都是偏底层的无态度的Web框架;egg.js是在koa的基础上做了一层很好的面向大型企业级应用的框架封装, 中小型项目推荐egg.js,上手快,概念易懂。

而这里,我们不需要关心那么多,直接用最原生的Express框架+Sequelize链接Mysql数据库。

安装环境

本地数据库
小白推荐大家安装,phpstudy,里面集成了Apache,Nginx,MySql,Ftp等

本地数据库管理工具,大家可以自行下载,有的可以忽略
链接:https://pan.baidu.com/s/15VSP0lgU7MXzqszWCFYXDQ
提取码:4hhz

支持链接数据库种类非常之多,免费、免费、免费。

(1)安装完成后,开始连接数据库

(2)双击打开连接后,右击连接名称,新建数据库

(3)库建好后,可以点击上面的新建表

(4)新建表时,点击添加字段,每个表都需要添加一个主键,可以默认勾选下面的自增,这样没插入一条数据,就会自动增长,不需要人工干预

(4)时间自动,create_time是每次插入都会记录插入的时间,update_time是每次更新数据时都会记录更新时间。记住设置的区别。

ok,有了第一个表,开始撸码时间

Express搭建一个web服务

1、本地工程下面新建一个package.json

{
  "name": "node-orm",
  "version": "1.0.0",
  "description": "",
  "author": "javan(www.javanx.cn)",
  "private": true,
  "scripts": {
    "dev": "cross-env NODE_ENV=development nodemon index.js --watch ./",
    "start": "cross-env NODE_ENV=production node index.js"
  }
}

2、安装插件

npm install express sequelize mysql2 cross-env --save
npm install nodemon --save-dev

3、根目录新建index.js


const express = require('express')
const app = express()

// 定义端口8111
app.listen('8111', function () {
  console.log("The server is running at *: 8111");
});

4、启动服务

npm run dev

打印"The server is running at *: 8111服务已经启动,打开浏览器,输入http://localhost:8111/

服务正常,接下来连接数据

Sequelize连接数据库

1、更目录新建config目录,存放项目的一些配置js,然后新建config/db.js

/**
 * mysql 数据库配置
 */

// 生成环境
let sqlConfig = {
  host: 'localhost',
  user: 'root',
  password: 'root',
  database: 'test',
  port: 3306
}

// 本地环境
// process.env.NODE_ENV 取决于package.json里面的配置
if(process.env.NODE_ENV !== 'production'){
  sqlConfig = {
      host: 'localhost',
      user: 'root',
      password: 'root',
      database: 'test',
      port: 3306
  };
}

module.exports = sqlConfig

2、更目录新建db目录,存放数据库model以及sequelize配置

此时项目目录

3、db/sequelize.js配置

var Sequelize = require('sequelize')
// 导入数据库配置
var db = require('../config/db')

var sequelize = new Sequelize(db.database, db.user, db.password, {
    logging: function(sql) {
        // logger为log4js的Logger实例
        if(process.env.NODE_ENV !== 'production'){
            console.log(sql)
        }
    },
    port:db.port,
    host: db.host,
    dialect: 'mysql',
    dialectOptions: {
        dateStrings: true,
        typeCast: true
    },
    pool: {
        max: 20,
        min: 1,
        acquire: 60000,
        idle: 10000
    },
    timezone: '+08:00' //东八时区
});

exports.sequelize = sequelize;

exports.defineModel = function (name, attributes) {
    var attrs = {};
    for (let key in attributes) {
        let value = attributes[key];
        if (typeof value === 'object' && value['type']) {
            value.allowNull = value.allowNull || false;
            attrs[key] = value;
        } else {
            attrs[key] = {
                type: value,
                // allowNull: false
            };
        }
    }
    attrs.version = {
        type: Sequelize.BIGINT,
        // allowNull: false
    };
    attrs.createUser = {
        type: Sequelize.STRING,
        allowNull: false
    };
    attrs.updateUser = {
        type: Sequelize.STRING,
        allowNull: false
    };
    return sequelize.define(name, attrs, {
        tableName: name,
        timestamps: true,
        paranoid: true, 
        charset: 'utf8mb4', 
        collate: 'utf8mb4_general_ci',
        hooks: {
            beforeBulkCreate: function(obj){
                obj.version = 0 ;
            },
            beforeValidate: function(obj){
                if(obj.isNewRecord){
                    console.log('first');
                    obj.version = 0 ; 
                }else{
                    console.log('not first');
                    obj.version = obj.version + 1 ;
                }
            }
        }
    });
};

4、db/model/user.js配置,这里的字段和数据库对应起来

/**
 * 用户
 */

 var Sequelize = require('sequelize');
 var {sequelize} = require('../sequelize.js');
 
 var user = sequelize.define('user',{
     id: {
         type: Sequelize.BIGINT(20),
         primaryKey: true,
         allowNull: false,
         unique: true,
         autoIncrement: true
     },
     name: Sequelize.STRING(255), // 名字
     age: Sequelize.BIGINT(11), // 年龄
     sex: Sequelize.BIGINT(1), // 性别
     create_time: Sequelize.DATE,
     update_time: Sequelize.DATE
 },{
     timestamps: false, // 不要默认时间戳 数据库没有时间戳字段时,设置为false,否则报错  SequelizeDatabaseError: Unknown column 'createdAt' in 'field list'
     freezeTableName: true 
 });
 
 module.exports = user;

Sequelize数据类型与数据库类型对应关系

Sequelize.STRING                      // VARCHAR(255)
Sequelize.STRING(1234)                // VARCHAR(1234)
Sequelize.STRING.BINARY               // VARCHAR BINARY
Sequelize.TEXT                        // TEXT
Sequelize.TEXT('tiny')                // TINYTEXT

Sequelize.INTEGER                     // INTEGER
Sequelize.BIGINT                      // BIGINT
Sequelize.BIGINT(11)                  // BIGINT(11)

Sequelize.FLOAT                       // FLOAT
Sequelize.FLOAT(11)                   // FLOAT(11)
Sequelize.FLOAT(11, 12)               // FLOAT(11,12)

Sequelize.REAL                        // REAL         仅限于PostgreSQL.
Sequelize.REAL(11)                    // REAL(11)     仅限于PostgreSQL.
Sequelize.REAL(11, 12)                // REAL(11,12)  仅限于PostgreSQL.

Sequelize.DOUBLE                      // DOUBLE
Sequelize.DOUBLE(11)                  // DOUBLE(11)
Sequelize.DOUBLE(11, 12)              // DOUBLE(11,12)

Sequelize.DECIMAL                     // DECIMAL
Sequelize.DECIMAL(10, 2)              // DECIMAL(10,2)

Sequelize.DATE                        // DATETIME 针对 mysql / sqlite, TIMESTAMP WITH TIME ZONE 针对 postgres
Sequelize.DATE(6)                     // DATETIME(6) 针对 mysql 5.6.4+. 小数秒支持多达6位精度
Sequelize.DATEONLY                    // DATE 不带时间.
Sequelize.BOOLEAN                     // TINYINT(1)

Sequelize.ENUM('value 1', 'value 2')  // 一个允许具有 “value 1” 和 “value 2” 的 ENUM
Sequelize.ARRAY(Sequelize.TEXT)       // 定义一个数组。 仅限于 PostgreSQL。
Sequelize.ARRAY(Sequelize.ENUM)       // 定义一个 ENUM 数组. 仅限于 PostgreSQL。

Sequelize.JSON                        // JSON 列. 仅限于 PostgreSQL, SQLite and MySQL.
Sequelize.UUID                        // PostgreSQL 和 SQLite 的 UUID 数据类型, CHAR(36) BINARY 针对于 MySQL (使用默认值: Sequelize.UUIDV1 或 Sequelize.UUIDV4 来让 sequelize 自动生成 ID)

Sequelize.GEOMETRY                    // 空间列.  仅限于 PostgreSQL (具有 PostGIS) 或 MySQL.
Sequelize.GEOMETRY('POINT')           // 具有几何类型的空间列.  仅限于 PostgreSQL (具有 PostGIS) 或 MySQL.
Sequelize.GEOMETRY('POINT', 4326)     // 具有几何类型和SRID的空间列.  仅限于 PostgreSQL (具有 PostGIS) 或 MySQL.

5、测试连接
index.js导入db/model/user.js测试一波

...
const user = require('./db/model/user')

user.findAll().then(data=>{
  console.log(data)
})

...

打印执行的sql,和结果,由于我们新建数据库没有插入数据,此时打印的是一个空数组[]

我们去数据库新建一条数据,大家看好我们只填入姓名、性别和年龄,id和时间都会自动插入

在查询一次,直接修改index.js,保存程序自动热更新

数据查询回来了,本节就到此结束了,希望大家都有所收获。