Sequelize

Sequelize 什么是Sequelize?Sequelize是一个基于Promise的NodeJS ORM模块什么是ORM?ORM(Object-Relational-Mapping)是对象关系映射对象关系映射可以把JS中的类和对象和数据库中的表和数据进行关系映射。映射之后我们就可以直接通过类和对象来操作数据表和数据了就不用编写SQL语句了ORM有效的解决了直接在NodeJS中编写SQL不够直观、不够高效、容易出错等问题。如何映射?在Sequelize中JS中的一个类(一个模型)就对应数据库中的一张表在Sequelize中JS中的一个对象就对应表中的一条数据(一条记录)在Sequelize中JS中的一个对象的属性就对应一条数据的一个字段|---------------------------| | id | name | age | | 1 | zs | 18 | | 2 | ls | 19 | |---------------------------|// 1.创建一张表cosnt 模型名称Sequelize.define(表名,{id:int,name:varchar(255),age:int})// 2.创建一条记录letzs模型名称.build({id:1,name:zs,age:18})// 3.操作表和数据只要是通过Sequelize定义的模型(类),那么Sequelize就会自动给这个模型添加很多操作表和数据的方法以后我们就可以直接通过模型操作表,通过模型创建出来的对象操作数据。sequelize连接数据库// 1.导入SequelizeconstSequelizerequire(sequelize);// 2.配置连接信息/* 第一个参数: 要操作的数据库名称 第二个参数: 数据库用户名 第三个参数: 数据库密码 第四个参数: 其它的配置信息 * */constsequelizenewSequelize(demo,root,root,{host:127.0.0.1,// MySQL服务器地址port:3306,// MySQL服务器端口号// 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库dialect:mysql,// 告诉Sequelize当前要操作的数据库类型pool:{max:5,// 最多有多少个连接min:0,// 最少有多少个连接idle:10000,// 当前连接多久没有操作就断开acquire:30000,// 多久没有获取到连接就断开}});// 3.测试配置是否正确sequelize.authenticate().then((){console.log(ok);}).catch((err){console.log(err);});什么是数据库连接池?默认情况下有一个人要使用数据库那么就必须创建一个连接默认情况下有一个人不用数据库了, 为了不占用资源, 那么就必须销毁一个连接。但是频繁的创建和销毁连接是非常消耗服务器性能的, 所以为了提升服务器性能就有了连接池。数据库连接池是负责分配、管理和释放数据库连接它允许应用程序重复使用一个现有的数据库连接而不是再重新建立一个。sequelize.sync() - 将已定义的所有 Model 同步到数据库表结构sequelize.sync()是 Sequelize ORM 中用于将已定义的所有 Model 同步到数据库表结构的方法。awaitsequelize.sync();默认行为awaitsequelize.sync();数据表不存在创建表。数据表已经存在通常不做处理。不会自动修改已有表结构例如新增或删除字段。常用选项// 根据 Model 尝试调整已有表结构awaitsequelize.sync({alter:true});alter: true会对比模型和数据库表并尝试修改表结构。存在误修改或数据丢失风险不建议用于生产环境。// 删除已有表再重新创建awaitsequelize.sync({force:true});force: true等价于“删表重建”会删除原有数据通常只用于本地开发或自动化测试。简单理解sequelize.sync()就是根据代码中定义的 Sequelize 模型创建数据库表。它适合开发和测试阶段。生产环境通常应使用 **Migration数据库迁移**管理表结构变化因为迁移记录明确、可审查、可回滚。Sequelize 官方也特别提醒不应在生产环境依赖sync({ alter: true })或sync({ force: true })。(sequelize.org)sequelize创建表字段说明常用属性type: 字段类型primaryKey: 是否是主键autoIncrement: 是否自动增长allowNull: 是否允许为空unique: 是否必须唯一defaultValue: 默认值额外配置常用属性timestamps: 是否自动添加createdAt/updateAt字段freezeTableName: 是否禁止自动将表名修改为复用tableName: 是否自定义表名一般不用indexes:[// 指定索引{name:,// 索引名称fields:[],// 索引字段名称}]实例/* sequelize.define(); 第一个参数: 用于指定表的名称 第二个参数: 用于指定表中有哪些字段 第三个参数: 用于配置表的一些额外信息 * *//* 注意点: 1.sequelize在根据模型创建表的时候, 会自动将我们指定的表的名称变成复数 2.sequelize在根据模型创建表的时候, 会自动增加两个字段 createAt/updateAt * */letUsersequelize.define(user,{id:{type:Sequelize.INTEGER,primaryKey:true,autoIncrement:true},name:{type:Sequelize.STRING,// varchar(255)allowNull:false,unique:true},age:{type:Sequelize.TINYINT,defaultValue:66},gender:{type:Sequelize.ENUM([男,女,妖]),defaultValue:妖}},{freezeTableName:true,// 告诉sequelize不需要自动将表名变成复数// tableName: student, // 自定义表名一般不用timestamps:false,// 不需要自动创建createAt/updateAt这两个字段indexes:[// 指定索引{name:idx_age,// 索引名称fields:[age],// 索引字段名称}]});// 注意点: 默认定义好一个模型之后并不会自动创建对应的表我们需要通过调用连接对象的sync方法来执行同步只有同步之后才会自动根据模型创建对应的表sequelize.sync();crud增// 下面这段代码 创建对象 save();letuawaitUser.create({name:ww,age:18,gender:女});console.log(u.dataValues);查在sequelize中模型就代表着表从表中查询数据即从模型中查询数据letuawaitUser.findByPk(2);console.log(u);改User.update({name:zs},{where:{id:2}})删User.destroy({where:{id:3}});条件查询letusawaitUser.findAll({where:{// id: 1// age: {// [Sequelize.Op.gte] : 33// },// id: 7// ------上面逗号分隔是并且关系下面是或者关系[Sequelize.Op.or]:{age:33,id:7}}});console.log(us.map(uu.dataValues));分页查询和排序// 分页letusawaitUser.findAll({offset:2// 跳过多少条数据});console.log(us.map(uu.dataValues));letusawaitUser.findAll({limit:2// 取多少条数据});console.log(us.map(uu.dataValues));letusawaitUser.findAll({offset:2,// 跳过多少条数据limit:2// 取多少条数据});console.log(us.map(uu.dataValues));// 排序letusawaitUser.findAll({order:[// [id, desc][age,desc],[id,desc]]});console.log(us.map(uu.dataValues));Sequelize关联查询一对一注意点:只要建立了人和书的关系, 那么在查询人的时候, 就可以把拥有的那本书也查询出来只要建立了书和人的关系, 那么在查询书的时候, 就可以把书属于哪个人也查询出来如果没有建立相关的关系, 那么就不能查询出相关的内容User.hasOne(Book,{// hasOne 谁拥有一个谁/ 一个人拥有一本书foreignKey:uId,sourceKey:id});Book.belongsTo(User,{// belongsTo 谁属于一个谁 / 一本书属于一个人foreignKey:uId,sourceKey:id});letuawaitUser.findOne({where:{id:1},// 注意点: 只要建立了表与表之间的关系, 那么在查询人的时候,就可以把这个人拥有的那本书也查询出来了include:{model:Book}});console.log(u.dataValues.book.dataValues);letbawaitBook.findOne({where:{id:1},// 注意点: 只要建立了表与表之间的关系, 那么在查询书的时候,就可以把这本书属于哪一个人也查询出来了include:{model:User}});console.log(b.dataValues.user.dataValues);一对多User.hasMany(Book,{// 一个人拥有多本书foreignKey:uId,sourceKey:id});Book.belongsTo(User,{// 一本书属于一个人foreignKey:uId,sourceKey:id})// 关联查询letuawaitUser.findOne({where:{id:1},include:{model:Book}});console.log(u.dataValues.books.map(bb.dataValues));letbawaitBook.findOne({where:{id:3},include:{model:User}});console.log(b.dataValues.user.dataValues);多对多// 创建模型letStudentsequelize.define(student,{id:{type:Sequelize.INTEGER,primaryKey:true,autoIncrement:true},name:{type:Sequelize.STRING,// varchar(255)allowNull:false,unique:true}},{freezeTableName:true,// 告诉sequelize不需要自动将表名变成复数// tableName: student, // 自定义表名timestamps:false// 不需要自动创建createAt/updateAt这两个字段});letTeachersequelize.define(teacher,{id:{type:Sequelize.INTEGER,primaryKey:true,autoIncrement:true},name:{type:Sequelize.STRING,// varchar(255)allowNull:false,unique:true}},{freezeTableName:true,// 告诉sequelize不需要自动将表名变成复数// tableName: student, // 自定义表名timestamps:false// 不需要自动创建createAt/updateAt这两个字段});letRelationsequelize.define(relation,{studentId:{type:Sequelize.INTEGER,allowNull:false,references:{model:Student,key:id}},teacherId:{type:Sequelize.INTEGER,allowNull:false,references:{model:Student,key:id}}},{freezeTableName:true,// 告诉sequelize不需要自动将表名变成复数// tableName: student, // 自定义表名timestamps:false// 不需要自动创建createAt/updateAt这两个字段});// 建立查询关系Student.belongsToMany(Teacher,{// 一个学生属于多个老师through:Relation});Teacher.belongsToMany(Student,{// 一个老师属于多个学生through:Relation});sequelize.sync();// 关联查询/* let s await Student.findOne({ where: { id: 1 }, include: { model: Teacher } }); console.log(s.dataValues.teachers.map(tt.dataValues)); */lettawaitTeacher.findOne({where:{id:1},include:{model:Student}});console.log(t);Sequelize-Cli什么是Sequelize-CLI?在编程开发中为了能够更好的管理代码, 我们可以使用Git来管理我们的代码,实现对代码变更的追踪, 实现在各个不同版本之间切换在数据库开发中为了能够更好的管理数据库, 我们也可以使用数据库迁移工具来管理我们的数据库,实现对数据库变更的追踪, 实现在各个不同版本之间切换Sequelize-CLI就是一款数据库迁移工具, 能够让我们追踪数据库的变更, 在各个不同版本之间随意切换Sequelize 中的timestamps: true如果定义模型时不显式关闭它Sequelize 会默认给模型加上两个时间字段createdAt updatedAt官方文档说明Sequelize 默认会自动为每个 model 添加createdAt和updatedAt类型通常是DataTypes.DATE并在创建、更新记录时自动维护它们。(sequelize.org)例如constUsersequelize.define(User,{name:DataTypes.STRING,});等价于默认启用constUsersequelize.define(User,{name:DataTypes.STRING,},{timestamps:true,});如果你不想要这两个字段可以这样关掉constUsersequelize.define(User,{name:DataTypes.STRING,},{timestamps:false,});UTC 是什么UTC是Coordinated Universal Time中文通常叫全球统一参考时间标准。例如中国使用的是北京时间 UTC 8所以UTC 时间2026-07-14 02:00:00 北京时间2026-07-14 10:00:00也就是说北京时间比 UTC 快 8 小时。Sequelize 和 数据库存的时间有什么关系在后端和数据库里经常建议数据库存 UTC 时间 前端展示时转换成本地时间原因是用户可能在不同时区服务器可能部署在不同时区UTC 不受夏令时、本地时区变化影响便于跨地区系统统一计算时间。例如数据库里存2026-07-14T02:00:00.000Z这里最后的Z通常表示UTC 时间也叫 Zulu time。前端给中国用户展示时可以转成2026-07-14 10:00:00