Sequelize 模型定义的正确姿势

Sequelize 是一个 Node.js 下的 ORM(Object-Relational Mapping)框架,用于实现数据对象(models)与数据库之间的映射关系。当使用 Sequelize 进行数据库操作时,每一个数据表都需要对应一个 Sequelize 模型对象,该对象用于定义表结构、属性以及数据操作等信息。在开发过程中,正确地定义 Sequelize 模型将有助于提高代码质量、开发效率和维护性。

基本定义方式

Sequelize 模型的定义主要由两部分组成:属性(attributes)和方法(methods)。属性定义表结构和字段属性,方法用于对数据进行操作。下面是一个简单的定义示例:

const { Sequelize, DataTypes } = require('sequelize');

const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql',
});

const User = sequelize.define('users', {
  name: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  age: {
    type: DataTypes.INTEGER,
    allowNull: false,
  },
}, {
  timestamps: true,
});

module.exports = User;

在这个示例中,我们先实例化了一个 Sequelize 对象,然后定义了一个 User 模型表示数据库中的 users 表。模型包含了两个属性:nameagename 属性的类型为 DataTypes.STRINGallowNull 属性设置为 false,表示该属性不能为空,age 属性的类型为 DataTypes.INTEGER。第三个参数配置了模型的一些选项,其中 timestamps 属性设置为 true 表示添加 createdAtupdatedAt 两个字段,分别表示创建时间和更新时间。

如何定义关联关系

Sequelize 提供了多种关联关系,包括一对一、一对多、多对多等关系。在定义关联关系时,我们需要考虑两个模型之间的关系类型(source/target)、关联关系的名称、外键的名称等因素。下面是一个定义一对多关系(一个用户拥有多个订单)的示例:

const Order = require('./order');

const User = sequelize.define('users', {
  name: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  age: {
    type: DataTypes.INTEGER,
    allowNull: false,
  },
}, {
  timestamps: true,
});

User.hasMany(Order, { as: 'orders', foreignKey: 'userId' });
Order.belongsTo(User, { as: 'user', foreignKey: 'userId' });

module.exports = User;

在这个示例中,我们定义了一个 Order 模型表示数据库中的 orders 表。在 User 模型中,我们使用 hasMany 方法定义了一个一对多的关联关系,关系名称为 orders,外键名称为 userId。在 Order 模型中,我们使用 belongsTo 方法定义了一个多对一的关系,关系名称为 user,外键名称也为 userId

如何定义校验规则

定义 Sequelize 模型时,我们可以通过设置属性的校验规则来保证数据的完整性和正确性。Sequelize 内置了常见的校验规则,如 allowNullisEmailisDateisInt 等等,也可以自定义校验规则。下面是一个定义校验规则的示例:

const User = sequelize.define('users', {
  name: {
    type: DataTypes.STRING,
    allowNull: false,
    validate: {
      len: [3, 50],
    },
  },
  email: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true,
    validate: {
      isEmail: true,
    },
  },
  age: {
    type: DataTypes.INTEGER,
    allowNull: false,
    validate: {
      min: 0,
    },
  },
}, {
  timestamps: true,
});

module.exports = User;

在这个示例中,我们使用了 lenisEmailmin 等校验规则,其中 len 表示 name 属性的值必须在长度 3 和 50 之间,isEmail 表示 email 属性的值必须是合法的 email 地址,min 表示 age 属性的值必须大于等于 0。

如何定义虚拟字段

虚拟字段(Virtuals)是指存在于模型中,但不会被存储到数据库中的字段。虚拟字段通常用于计算或处理其他已存储字段的值。Sequelize 通过调用 getset 方法来实现对虚拟字段的访问。下面是一个定义虚拟字段的示例:

const User = sequelize.define('users', {
  fullName: {
    type: DataTypes.VIRTUAL,
    get() {
      return `${this.get('firstName')} ${this.get('lastName')}`;
    },
    set(value) {
      const names = value.split(' ');
      this.set('firstName', names[0]);
      this.set('lastName', names[1]);
    }
  },
  firstName: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  lastName: {
    type: DataTypes.STRING,
    allowNull: false,
  },
});

module.exports = User;

在这个示例中,我们定义了一个虚拟字段 fullName,通过 get 方法来获取虚拟字段的值,通过 set 方法来设置虚拟字段的值。同时,我们也定义了 firstNamelastName 两个实际存在于数据库中的字段。

如何运用 Hooks

Hooks 是指在进行数据库操作时,自动执行的回调函数,用于在执行数据库操作前、后对数据进行相关处理。Sequelize 提供了多种 Hooks,包括 BeforeValidate、BeforeCreate、BeforeBulkCreate、AfterCreate 等等。下面是一个定义 Hooks 的示例:

const User = sequelize.define('users', {
  name: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  age: {
    type: DataTypes.INTEGER,
    allowNull: false,
  },
}, {
  timestamps: true,
});

User.beforeValidate((user) => {
  if (user.age < 0) {
    throw new Error('Age must be greater than 0');
  }
});

module.exports = User;

在这个示例中,我们使用了 beforeValidate Hook 来验证 User 模型中的 age 属性,如果该属性小于 0,将会抛出一个错误。

总结

Sequelize 是一个优秀的 ORM 框架,Sequelize 模型的正确定义对于项目的性能和可维护性具有重要的影响。本文通过介绍 Sequelize 模型定义的基本方式、关联关系、校验规则、虚拟字段和 Hooks,希望能够为读者提供更多的技术指导和借鉴。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a22ab5add4f0e0ffa38b03


纠错反馈