前言

记录一下ORM Sequelize升级到v5的过程中涉及到的几个地方。
升级v6和v5 差别不大。

记录

升级命令

1
$ npm i sequelize@5

操作符替换(Operator)

  • v4是v3与v5的过渡版本,到了v5版本 $ 操作符已经被删除

  • v5操作符将 $ 操作符替换为了 Op 操作符(eg. $or换为了Op.or)

    1
    2
    3
    4
    5
    6
    7
    8
    // index.js
    const Sequelize = require("sequelize");

    const db = {};
    db.sequelize = sequelize;
    db.Sequelize = Sequelize;
    db.Op = Sequelize.Op;
    module.exports = db;
1
2
3
4
5
6
// file.js
const models = require('./index');

const where = {};
// where.$or = [];
where[models.Op.or] = [];
  • 升级时未减少修改可以将Op挂载到导出的models模块,全局替换修改即可

格式化操作符

  • 当时用JSON.stringify()格式化where时,由于models.Op.or返回的是Symbol类型,所以格式化后会为空(表现为where Symbol属性条件丢失)
  • 通常这个错误很难被发现,也不会报错,但是当我们在include中引用这个格式化后的where且include的required属性设为true时,就会引发错误(原因就是全连接时条件为空),当然其他情况也可能发生错误。
  • 如果项目中设计到操作符格式化,可以考虑格式化前使用$操作符,格式化后,再将操作符转换为Symbol类型

下划线标记(underscored)

  • 目前我测试的只对列起作用

  • 在初始化mysql时,可以使用underscored属性声明列为下划线格式,默认为驼峰格式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    const Sequelize = require("sequelize");
    const sequelize = new Sequelize(
    db,
    user,
    pass,
    {
    dialect: 'mysql',
    host,
    3306,
    define: {
    'underscored': true
    },
    pool: {
    max: 30,
    min: 1,
    idle: 30000
    },
    logging: env === 'development' ? console.log : false,
    benchmark: env === 'development' // 输出日志时打印时间
    });
  • 如果表中部分列使用的是驼峰命名,可以使用field属性进行声明

    1
    2
    3
    4
    5
    weekMark: {
    field: 'weekMark',
    type: DataTypes.STRING(20),
    allowNull: false
    }

时间戳设置(timestamps)

  • v5默认使用驼峰命名

  • 文档中提到underscored可以适用于外键、列、时间戳,但我试的只有列起作用了 O.o

  • 在模型定义的options中可以设置createdAt和updatedAt来设置时间戳的命名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    "use strict";
    module.exports = function (sequelize, DataTypes) {
    return sequelize.define(
    "ExpressConfig", {
    id: {
    type: DataTypes.INTEGER(),
    allowNull: false,
    primaryKey: true,
    autoIncrement: true
    }
    },{
    createdAt: 'created_at',
    updatedAt: 'updated_at',
    timestamps: true,
    freezeTableName:true,
    tableName:'User'
    });
    };

外键设置

  • 外键同样默认使用驼峰命名

  • 使用下划线命名时需要显式设置

    1
    2
    3
    4
    UserRole.hasMany(models.User, {
    foreignKey: "role_id",
    sourceKey: "id"
    });

undefined

  • 在插入数据时,若值为undefined时,会默认忽略该列,与V4无变化

  • 在查询数据时,若where条件的值为undefined时,会报错(V4中会默认为null)

当列字段包含 $ 字符时

  • v5中在生成sql语句试,会使用正则表达式**/$($|\w+)/g去查找替换,所以当列字段包含 $ 字符时,会匹配失败,导致执行更新插入操作时报错Named bind parameter “${match}” has no value in the given object.**

  • v6中虽然修复过此bug,但是只是不再匹配单词中间的 $,单词前边的的 $ 字符还是会匹配到

  • 为了不影响其它地方使用,可以考虑修改字段名并结合field字段避免

  • 也可以用原生语句替换

总结

  • 只记录了部分升级过程的错误