从 Sequelize 迁移到 TypeORM:数据源、实体定义、字段选项与索引的完整对照指南

发布时间:2026/11/5 12:35:22

从 Sequelize 迁移到 TypeORM:数据源、实体定义、字段选项与索引的完整对照指南 从 Sequelize 迁移到 TypeORM数据源、实体定义、字段选项与索引的完整对照指南【免费下载链接】typeormTypeScript JavaScript ORM for Node.js — supports PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle, and more.项目地址: https://gitcode.com/GitHub_Trending/ty/typeorm本文是一份面向 Sequelize 存量项目的 TypeORM 迁移实战指南核心围绕“同一个需求在 Sequelize 与 TypeORM 中各自的写法”展开从数据源初始化、表结构同步到实体模型与各种字段约束可空、默认值、唯一、自增、主键、时间戳列再到模型的新增/更新与多列索引创建均给出可直接对照、可运行的代码。读完本文你能够把一段现有的 Sequelize 模型代码逐行翻译成 TypeORM 的实体定义并了解底层装饰器与DataSource的实现机制做到“知其然也知其所以然”。本文内容以 迁移指南 为骨架代码示例、结论均可在此文档与仓库源码中找到依据。一、初始化数据源从new Sequelize(...)到new DataSource({...})在 Sequelize 中数据源连接配置通过new Sequelize(database, username, password, options)创建随后调用authenticate()验证连接是否成功const sequelize new Sequelize(database, username, password, { host: localhost, dialect: mysql, }) sequelize .authenticate() .then(() { console.log(Data Source has been initialized successfully.) }) .catch((err) { console.error(Error during Data Source initialization:, err) })TypeORM 中使用DataSource承载相同的职责但它把连接参数统一收进一个选项对象并用type字段取代 Sequelize 的dialectimport { DataSource } from typeorm const dataSource new DataSource({ type: mysql, host: localhost, username: username, password: password, }) dataSource .initialize() .then(() { console.log(Data Source has been initialized successfully.) }) .catch((err) { console.error(Error during Data Source initialization:, err) })两者最直观的差异是构造签名维度SequelizeTypeORM构造方式位置参数(database, user, password) 选项全部使用选项对象{ type, host, username, password, database }数据库类型字段dialect: mysqltype: mysql连接验证/初始化authenticate()initialize()可用范围需要传入各模型全局导出后可在任意模块使用几点迁移要点推荐在单独文件中创建DataSource实例并export这样应用各处都能复用同一连接。官方 DataSource 指南 同样建议“把AppDataSource通过export全局暴露”并且一个应用可以按需创建多个数据源例如 MySQL 一个、Postgres 一个。不要忘记type是可选的数据库平台集合mysql、postgres、mariadb、sqlite、mssql、oracle、mongodb等DataSource接受的DataSourceOptions会随type不同而提供不同字段。更多参数含义见 DataSourceOptions。从源码看initialize()是真正的“建连 初始化元数据”入口DataSource.ts并且在满足条件时还会触发自动建表见下文同步机制。二、表结构同步从逐模型sync()到synchronize: trueSequelize 中要为每个模型单独同步表结构Project.sync({ force: true }) Task.sync({ force: true }){ force: true }表示“先 DROP 再 CREATE”容易造成数据丢失。TypeORM 则把“是否自动同步”做成了数据源级开关只需在选项里加一个布尔值const dataSource new DataSource({ type: mysql, host: localhost, username: username, password: password, synchronize: true, })此时 TypeORM 会在启动时根据你注册的所有实体entities自动比对并创建/更新表结构。源码层面initialize()在建立连接后会检查this.options.synchronize为真则调用内部synchronize()方法DataSource.ts。生产环境提示synchronize: true适合开发期快速迭代在真实生产环境里更稳妥的做法是把它关闭改用显式的 Migrations 机制 通过迁移文件管理结构变更可审计、可回滚。Sequelize 生态同样有独立迁移工具TypeORM 则把迁移作为一等公民内置。三、定义模型从sequelize.define到实体类EntitySequelize 用sequelize.define(tableName, attributes)工厂函数定义模型module.exports function (sequelize, DataTypes) { const Project sequelize.define(project, { title: DataTypes.STRING, description: DataTypes.TEXT, }) return Project }module.exports function (sequelize, DataTypes) { const Task sequelize.define(task, { title: DataTypes.STRING, description: DataTypes.TEXT, deadline: DataTypes.DATE, }) return Task }在 TypeORM 中模型被命名为Entity实体——一个普通 TypeScript 类配合装饰器声明式地描述表结构import { Entity, PrimaryGeneratedColumn, Column } from typeorm Entity() export class Project { PrimaryGeneratedColumn() id: number Column() title: string Column() description: string }import { Entity, PrimaryGeneratedColumn, Column } from typeorm Entity() export class Task { PrimaryGeneratedColumn() id: number Column() title: string Column(text) description: string Column() deadline: Date }迁移建议与约定一个实体类放一个文件这是社区强烈推荐的实践也便于通过 glob 批量注册实体。Entity()标记类映射到数据库表默认表名取类名Project→project也可显式指定Entity(my_table_name)。PrimaryGeneratedColumn()声明自增主键Column()声明普通列。类型映射DataTypes.STRING通常对应默认字符串列DataTypes.TEXT需要显式写成Column(text)示例中正是如此DataTypes.DATE对应实体里的Date属性。TypeORM 允许把类直接当作数据库模型使用并“以声明式方式说明模型的哪一部分会成为数据库表列”。同时TypeScript 的类型系统会为这些类带来类型提示type hinting等额外收益——这是相比纯 JS 的 Sequelize 模型的一大优势。值得留意的是实体中每个被Column()标记的属性最终都会映射为表的一列列的数据库类型既可以通过Column第一个参数显式给出如Column(text)也可以不写、让 TypeORM 依据属性反射元数据自动推断。实体必须拥有主键列关系型场景否则会报错。字段类型、主键列、特殊列的完整展开可参考 Entities 文档。四、其他模型设置Sequelize 字段选项 →Column选项这是迁移中最琐碎也最常碰到的部分。下面逐条给出“Sequelize 写法 → TypeORM 写法”的对照。4.1 可空 默认值Sequelizeflag: { type: Sequelize.BOOLEAN, allowNull: true, defaultValue: true },TypeORM 使用nullable与default两个列选项Column({ nullable: true, default: true }) flag: boolean;4.2 数据库当前时间作为默认值Sequelizeflag: { type: Sequelize.DATE, defaultValue: Sequelize.NOW }TypeORMColumn({ default: () NOW() }) myDate: Date;这里用函数形式default: () NOW()让默认值落到数据库侧的NOW()生成数据库层面的DEFAULT而不是在 JS 侧先计算一个固定时间。4.3 唯一约束SequelizesomeUnique: { type: Sequelize.STRING, unique: true },TypeORMColumn({ unique: true }) someUnique: string;从源码看Column({ unique: true })会被拆成两步处理一方面注册普通列元数据另一方面向uniques元数据集合登记一条唯一约束Column.ts最终在数据库中生成唯一约束或唯一索引。4.4 数据库列名与属性名不一致Sequelize 用field指定物理列名fieldWithUnderscores: { type: Sequelize.STRING, field: field_with_underscores },TypeORM 中对应的是nameColumn({ name: field_with_underscores }) fieldWithUnderscores: string;默认情况下 TypeORM 会用属性名生成列名需要别名时用name覆盖。4.5 自增列SequelizeincrementMe: { type: Sequelize.INTEGER, autoIncrement: true },TypeORMColumn() Generated() incrementMe: number;Generated()用于标记“插入实体时自动生成值”的非主键列。其默认生成策略为increment源码 Generated.ts 中strategy: increment | uuid | rowid increment另外也支持Generated(uuid)。需要留意的是部分数据库只允许一张表存在一个 increment 列或要求自增列必须是主键若遇阻可改用PrimaryGeneratedColumn()。4.6 手动主键Sequelizeidentifier: { type: Sequelize.STRING, primaryKey: true },TypeORMColumn({ primary: true }) identifier: string;Column({ primary: true })等价于使用PrimaryColumn()。若希望该主键自增或生成 UUID则应使用PrimaryGeneratedColumn()/PrimaryGeneratedColumn(uuid)。4.7createDate/updateDate时间戳列Sequelize 通常需要手动配置createdAt/updatedAt。TypeORM 为此提供了专用的时间戳列装饰器不必每次手写默认值CreateDateColumn(); createDate: Date; UpdateDateColumn(); updateDate: Date;CreateDateColumn()会在对象首次插入时写入创建时间且此后不再变动实现上以mode: createDate注册列元数据CreateDateColumn.tsUpdateDateColumn()则在每次执行save/upsert命中更新分支时自动刷新为当前时间。列名可由你自由命名。除上述对照外Column还支持更丰富的选项例如lengthvarchar(150)、comment、precision/scale、select查询默认是否隐藏该列、transformer读写时类型转换等详见 Entity columns 章节。上述多数选项为关系型数据库专用在 MongoDB 驱动下不可用。4.8 小结对照表Sequelize 属性选项TypeORM 写法说明allowNull: truenullable: true列是否允许 NULLdefaultValue: valuedefault: value列默认值defaultValue: Sequelize.NOWdefault: () NOW()数据库侧当前时间unique: trueunique: true生成唯一约束field: db_namename: db_name指定物理列名autoIncrement: trueColumn()Generated()自增值生成primaryKey: trueprimary: true或PrimaryColumn()声明主键createdAt/updatedAtCreateDateColumn()/UpdateDateColumn()自动时间戳五、使用模型新增、保存、加载与属性访问5.1 创建并保存新模型Sequelize 通过Model.create(object)一行完成“创建 落库”const employee await Employee.create({ name: John Doe, title: senior engineer, })TypeORM 提供了多种等价途径你可以按团队偏好选择Data Mapper或Active Record两种模式这也是 Sequelize 迁移到 TypeORM 后最需要适应的编程风格差异。Data Mapper 风格默认实体只描述属性通过仓库Repository操作数据库。const employee new Employee() // 也可以在构造函数中传参 employee.name John Doe employee.title senior engineer await dataSource.getRepository(Employee).save(employee)Active Record 风格实体继承BaseEntity直接在模型上提供save、find等静态与实例方法。const employee Employee.create({ name: John Doe, title: senior engineer }) await employee.save()BaseEntity.create是Repository.create的静态等价物BaseEntity上还提供preload、save、remove、findOneBy等一系列对应方法见 BaseEntity.ts 中的静态方法实现。两种模式各有取舍Data Mapper 在大型应用中更利于维护职责分离Active Record 在小型项目中更简洁直接。完整对比见 Active Record vs Data Mapper。5.2 预加载并替换已存在实体如果想从数据库加载一条已存在记录并仅替换其中部分属性两种风格都能用preloadconst employee await Employee.preload({ id: 1, name: John Doe })注意它的语义给定对象必须携带主键idTypeORM 先按该主键查出完整实体再用传入对象中的属性做覆盖若对应 id 不存在则返回undefined。其底层经由Repository.preload转发给EntityManager.preloadRepository.ts。相比 Sequelize 先findByPk再手动赋值的惯用法preload一步到位。5.3 访问属性Sequelize 中属性需要经过实例的get()方法console.log(employee.get(name))TypeORM 的实体就是普通类实例直接访问属性即可console.log(employee.name)这带来的直接收益是IDE 自动补全 编译期类型检查成为常态字符串键拼错的问题可以在编译阶段被拦截。Repository/BaseEntity上其余常用 APIfind、findOneBy、findAndCount、save、remove、softDelete、update、upsert、分页选项等的完整签名可查阅 Repository API。六、创建索引从indexes配置到Index装饰器Sequelize 在define的第三个参数里集中配置索引数组sequelize.define( user, {}, { indexes: [ { unique: true, fields: [firstName, lastName], }, ], }, )TypeORM 把索引以装饰器形式直接附着在实体/列上。上面的“复合唯一索引”等价写法是把Index放在类上并传入参与索引的列名数组Entity() Index([firstName, lastName], { unique: true }) export class User {}Index在 Index.ts 中提供多种重载形态按需选用单列索引直接标注在列属性上如Index()加在Column()上带名索引Index(name-idx)列级唯一索引Index({ unique: true })实体级多列索引Index([col1, col2])可加{ unique: true }变成复合唯一索引。单一列唯一约束更常见的是直接写Column({ unique: true })。空间索引spatial: true、synchronize关闭后配合迁移脚本手工建索引等更多场景参见 Indexes 完整文档。七、迁移路线总结与进一步阅读把上述各节串起来一条典型的 Sequelize → TypeORM 迁移路径是建数据源把new Sequelize(db, user, pass, { host, dialect })换成导出的new DataSource({ type, host, username, password, database, entities })小步同步开发期打开synchronize: true验证结构生产切到 Migrations改写模型把每个sequelize.define(...)文件改写成“一个实体类一个文件”并用Entity/Column系列装饰器逐字段翻译类型与约束替换读写把Model.create、model.get(x)、Model.update等调用点改造成 Repository / EntityManager / BaseEntity 风格平移索引把模型第三参的indexes配置翻译成列级或实体级Index。每一步都可以回到对应官方文档做深度补充数据源与连接生命周期见 DataSource 指南 与 DataSourceOptions 参数说明实体与列的细节见 Entities 文档仓储层完整 API 见 Repository API编程范式选型见 Active Record vs Data Mapper。对于仓库中的真实实现可继续阅读 DataSource.ts、Column.ts、Generated.ts、BaseEntity.ts 等源码文件验证本文所述机制。【免费下载链接】typeormTypeScript JavaScript ORM for Node.js — supports PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle, and more.项目地址: https://gitcode.com/GitHub_Trending/ty/typeorm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/4 16:22:03

金迪宝GDB702关机展示指南:外观检查与拍摄流程详解

金迪宝GDB702 这类入门级手机,真正被用户、卖家或数码爱好者“看清楚”的时刻,往往不是开机亮屏,而是关机之后。开机状态下,桌面壁纸、系统字体、通知栏和预装软件会分散注意力;关机展示反而能把整台机器还原为纯粹的硬…

2026/11/4 9:30:31

时空数据气象预测实战:从地球物理建模到深度学习部署

简介:Navicat for MySQL for Mac是一款面向Mac平台的MySQL数据库管理工具,适合数据库管理员、开发人员以及数据分析人员,用于高效完成多服务器连接、数据查询编辑、备份恢复、结构同步和数据建模等日常任务。该压缩包约49.92MB,文…

2026/11/5 12:29:32

Text to SQL系统第三层实现:复杂查询意图识别与优化

1. 项目概述Text to SQL系统作为自然语言处理与数据库技术交叉领域的重要应用,正在深刻改变着非技术人员与数据库交互的方式。这个看似简单的"输入问题,输出SQL"功能背后,隐藏着复杂的实现逻辑和技术挑战。今天我们就来拆解这个系统…

2026/11/5 12:29:32

Text-to-SQL系统架构解析与性能优化实践

1. 文本到SQL转换系统的核心价值 在数据驱动的时代,SQL作为与数据库交互的标准语言,其重要性不言而喻。但编写SQL查询需要专业技能,这成为了许多非技术用户获取数据的障碍。Text-to-SQL系统正是为解决这一痛点而生,它允许用户用自…

2026/11/5 12:29:32

钉钉办公自动化:OpenClaw Skill原理与应用

1. 项目概述 OpenClaw Skill是一个基于自动化原理设计的办公效率工具,专门针对钉钉平台的操作优化。它能模拟人工操作流程,实现消息自动收发、审批流程处理、考勤数据管理等高频办公场景的自动化。我在实际使用中发现,这个工具特别适合需要频…

2026/11/5 12:29:32

AI编程辅助工具:5个提升代码可用性的Prompt模板

1. 项目背景与核心价值 去年团队引入AI编程辅助工具时,我们经历了从"玩具demo"到"生产级应用"的艰难跨越。最深的体会是:需求沟通的质量直接决定了AI产出的可用性。那些模糊的"做个用户管理系统"之类的需求,AI…

2026/11/5 12:24:32

云原生智能体协同架构在城市轨道交通中的应用

1. 新一代城市轨道交通云原生智能体协同架构概述城市轨道交通作为现代都市的"大动脉",其运营效率和服务质量直接影响着千万市民的日常生活。近年来,随着云计算、人工智能等技术的快速发展,传统的轨道交通智能化系统架构正面临着前所…

2026/11/5 12:14:29

Stimulsoft Reports 2019.2.2 落地指南:老系统兼容与版本陷阱规避

简介:Stimulsoft Reports 2019.2.2 是一款面向.NET开发者的专业报表控件,适用于WinForms、ASP.NET及WPF平台,帮助开发者快速构建数据可视化报表与打印输出功能,尤其适合中高级C#工程师在企业级管理系统、BI看板或财务报表模块中集…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑