发布说明 1.0
TypeORM 1.0 是一个重大版本,移除了长期弃用的 API,现代化了平台要求,并带来了在 0.3.x 周期中积累的数十个错误修复和新功能。
破坏性变更
有关详细的升级说明,请参阅 升级指南。
平台要求
- 要求 Node.js 20+ — 已移除对 Node.js 16 和 18 的支持,最低 JavaScript 目标版本现为 ES2023 (#11382 by @alumni)
- 移除
Bufferpolyfill — 现在在非 Node 平台上使用Uint8Array处理二进制数据;Node.jsBuffer(继承自Uint8Array)继续像以前一样工作 (#11935 by @pujux) - 替换 Glob 库 —
glob已替换为tinyglobby,rimraf已被移除,减少了依赖项 (#11699 by @alumni) - 哈希迁移至原生
crypto—sha.js和uuid包已被原生crypto模块和crypto.randomUUID()替代 (#11864 by @G0maa, #11769 by @mag123c)
驱动变更
- MySQL / MariaDB:弃用
mysql包 — 仅支持mysql2;已移除connectorPackage选项 (#11766 by @pkuczynski) - MySQL:
legacySpatialSupport默认值改为false— 默认使用标准的ST_GeomFromText/ST_AsText函数 (#12083 by @pkuczynski) - MySQL:移除
width和zerofill列选项 — 这些选项在 MySQL 8.0.17 中已被弃用,并在 MySQL 8.4 中移除 (#12084 by @pkuczynski) - SQLite:弃用
sqlite3,better-sqlite3成为默认驱动 — 不再支持sqlite3包;已移除flags和busyTimeout选项 (#11836 by @pkuczynski) - MongoDB:要求驱动 v7+ — 已放弃对 MongoDB Node.js 驱动 v5/v6 的支持;移除
stats()方法;移除已弃用的连接选项;不再导出内部类型 (#12208 by @naorpeled, #12179 by @pkuczynski, #12120 by @pkuczynski, #12037 by @alumni) - MS SQL Server:移除
domain连接选项 — 请改用类型为 NTLM 的authentication选项 (#12135 by @pkuczynski) - MS SQL Server:
options.isolation重命名为options.isolationLevel— 值格式从READ_COMMITTED更改为READ COMMITTED以匹配IsolationLevel类型;新增SNAPSHOT隔离级别 (#12231 by @Cprakhar) - SAP HANA:移除已弃用的连接别名 — 已移除
hanaClientDriver、pool.max、pool.requestTimeout、pool.idleTimeout等选项,请改用其现代等效选项 (#12080 by @gioboa) - Expo:移除旧版驱动 — 已移除旧版 Expo SQLite 驱动;请使用 Expo SDK v52+ 及现代异步 API (#11860 by @G0maa)
- Redis:移除旧版客户端支持 — 查询结果缓存仅支持现代 Redis 客户端(v4+) (#12057 by @G0maa)
移除的 API
Connection和ConnectionOptions已移除 — 改用DataSource和DataSourceOptions(#12022 by @alumni).connection属性重命名为.dataSource—Driver、QueryRunner、EntityManager、QueryBuilder、EntityMetadata以及所有*Event订阅器接口上的connection属性已重命名为dataSource;提供了一个已弃用的 getter 作为桥接 (#12244, #12245, #12246, #12249 by @pkuczynski)ConnectionManager和全局便捷函数移除 —createConnection、getConnection、getManager、getRepository、createQueryBuilder以及其他全局项已移除 (#12098 by @michaelbromley)getMongoRepository和getMongoManager全局移除 — 改用dataSource.getMongoRepository()和dataSource.mongoManager(#12099 by @pkuczynski)DataSource.name已移除 — 在 v0.3 中已弃用命名连接;ConnectionOptionsReader.all()重命名为get()(#12136 by @pkuczynski)- 移除对
TYPEORM_*环境变量的支持 —ConnectionOptionsEnvReader、ormconfig.env和dotenv自动加载已移除 (#12134 by @pkuczynski) findByIds已移除 — 改用findBy并搭配In操作符 (#12114 by @pkuczynski)findOneById已移除 — 改用findOneBy(#12198 by @pkuczynski)Repository.exist()已移除 — 改用Repository.exists()(#12131 by @pkuczynski)AbstractRepository、@EntityRepository和getCustomRepository已移除 — 改用Repository.extend()(#12096 by @pkuczynski)- 移除
@RelationCount装饰器 — 请改用带子查询的@VirtualColumn(#12181 by @pkuczynski) - 移除 IoC 容器系统 —
useContainer()、getFromContainer()以及相关类型已移除 (#12180 by @pkuczynski) - 移除
readonly列选项 — 改用update: false(#12132 by @pkuczynski) - 移除
ColumnNumericOptions上的unsigned— 仅影响 decimal/float 类型;整数的unsigned保持不变 (#12133 by @pkuczynski) - QueryBuilder:移除
onConflict()、弃用的orUpdate()重载,以及setNativeParameters()— 改用orIgnore()/orUpdate()的数组签名,并使用setParameters()(#12090 by @pkuczynski) - QueryBuilder:移除
printSql()— 由于所有已执行的查询都会通过已配置的 logger 记录,因此它是多余的;如需检查 SQL,请使用getSql()或getQueryAndParameters()(#12151 by @naorpeled, #12220 by @pkuczynski) - QueryBuilder:移除
WhereExpression类型别名 — 改用WhereExpressionBuilder(#12097 by @pkuczynski) - QueryBuilder:移除
replacePropertyNames()— 它是一个空操作(no-op) (#12178 by @pkuczynski) - 移除
join查找选项 — 对于 LEFT JOIN 使用relations,对于其他 join 类型请使用 QueryBuilder (#12188 by @pkuczynski) - 移除基于字符串的
select— 请改用对象语法select: { id: true },而不是select: ["id"](#12214 by @pkuczynski) - 移除基于字符串的
relations— 请改用对象语法relations: { profile: true },而不是relations: ["profile"](#12215 by @pkuczynski) - 移除已弃用的锁模式 —
pessimistic_partial_write和pessimistic_write_or_fail已被pessimistic_write(并配合onLocked选项)替代 (#12093 by @pkuczynski) - 移除
QueryRunner.loadedTables和loadedViews— 改用getTables()和getViews()(#12183 by @pkuczynski) - 移除
MigrationExecutor.getAllMigrations()— 改用getPendingMigrations()、getExecutedMigrations()或dataSource.migrations(#12142 by @pkuczynski) - 移除
EntityMetadata.createPropertyPath()静态方法 — 内部工具,没有公开的替代方案 (#12141 by @pkuczynski) - 从驱动和查询构建器中移除内部
nativeParameters相关管道 (#12104 by @pkuczynski) - 从 Broadcaster 中移除内部
broadcastLoadEventsForAll()(#12137 by @pkuczynski) - 移除内部
DriverUtils.buildColumnAlias()— 改用buildAlias()(#12138 by @pkuczynski) - 移除
RdbmsSchemaBuilder.renameTables()— 一个空的 no-op 方法,且从未被调用 (#12284 by @naorpeled) - 移除
EntityMetadata.getValueMap()的options参数 —skipNulls选项从未生效;移除第三个参数 (#12303 by @naorpeled)
行为变更
- 现在不可为空的关系使用 INNER JOIN — 对于标记为
nullable: false的ManyToOne以及拥有方OneToOne关系,改用INNER JOIN而不是LEFT JOIN,这可能会排除具有孤立外键(orphaned foreign keys)的行 (#12064 by @pkuczynski) invalidWhereValuesBehavior默认值为throw— 在 where 条件中传入null或undefined现在会抛出错误,而不是静默忽略该属性;若要匹配 null,请使用IsNull()(#11710 by @naorpeled)invalidWhereValuesBehavior仅影响高级 API — QueryBuilder 的.where()、.andWhere()、.orWhere()不再受此设置影响 (#11878 by @naorpeled)ConnectionOptionsReader和FileLogger路径从process.cwd()解析 —ConnectionOptionsReader不再使用app-root-path来定位ormconfig文件;改为搜索process.cwd()。如需覆盖,请在构造函数中传入{ root: "/custom/path" }。FileLogger.logPath也同样从process.cwd()解析 — 当应用不是从其根目录启动时,请使用绝对路径 (#12257 by @alumni)
新功能
查询构建器
INSERT INTO ... SELECT FROM ...—InsertQueryBuilder新增valuesFromSelect()方法,用于数据迁移和转换查询 (#11896 by @Cprakhar)- update/upsert 的
returning选项 — 仓库和实体管理器的update()和upsert()方法现在在支持RETURNING子句的数据库上支持returning选项 (#11782 by @naorpeled) - 所有 drop 方法的
ifExists参数 —dropColumn、dropIndex、dropPrimaryKey、dropForeignKey、dropUniqueConstraint、dropCheckConstraint、dropExclusionConstraint及其复数变体现在接受ifExists标志 (#12121 by @pkuczynski) QueryRunner的显式资源管理 — 支持await using语法(TypeScript 5.2+)实现自动清理 (#11701 by @alumni)
Transactions
- 所有驱动的 DataSource 级默认隔离级别 —
DataSourceOptions.isolationLevel现在会被每一个支持事务的驱动所遵从,而不仅仅是 SQL Server。通过 DataSource 启动的事务(显式或隐式用于 DML)默认使用该级别 (#12269 by @pkuczynski) - Aurora Postgres:事务隔离级别支持 — Aurora Postgres 现在会遵从
isolationLevel选项,无论是在 DataSource 上还是在显式调用startTransaction()时 (#12334 by @pkuczynski) - Spanner:事务隔离级别支持 — Google Spanner 现在会遵从
isolationLevel选项。Spanner 的supportedIsolationLevels仅限于REPEATABLE READ(目前为预览)和SERIALIZABLE(#12335 by @pkuczynski)
Drivers
- PostgreSQL:枚举变更的
ADD VALUE— 在添加新的枚举值时,TypeORM 在可能的情况下会使用更简单的ALTER TYPE ... ADD VALUE语法,而不是 4 步的重命名-创建-迁移-删除方案 (#10956 by @janzipek) - PostgreSQL:额外扩展 — 新增
installExtensions选项,用于在连接初始化期间安装额外的 PostgreSQL 扩展 (#11888 by @Cprakhar) - PostgreSQL:部分索引支持 — 增加对 PostgreSQL 部分索引的支持 (#11318 by @freePixel)
- SAP HANA:在 SELECT 中加锁 —
FOR UPDATE以及其他锁模式现在在 SAP HANA 查询中得到支持 (#11996 by @alumni) - SAP HANA:表注释 —
@Entity({ comment: "..." })现在可在 SAP HANA 上工作 (#11939 by @Cprakhar) - SAP HANA:连接池超时 — 新增
maxWaitTimeoutIfPoolExhausted连接池选项 (#11868 by @alumni) - SQLite:
jsonb列类型 — SQLite 现在支持jsonb列类型 (#11933 by @Cprakhar) - MongoDB:基于对象的
select投影 —find*()方法现在除了现有的字符串数组形式外,还接受其他驱动使用的相同对象形式select语法(select: { id: true, name: true }) (#12237 by @pkuczynski) - React Native:加密密钥 — 为 React Native SQLite 数据库新增用于传递加密密钥的选项 (#11736 by @HtSpChakradharCholleti)
持久化与插入更新
clear()中的级联截断 —Repository.clear()和EntityManager.clear()现在接受{ cascade: true }以在 PostgreSQL、CockroachDB 和 Oracle 上执行TRUNCATE ... CASCADE(#11866 by @Cprakhar)increment/decrement的更好的类型 — 条件参数现在使用正确的实体感知类型,而非any(#11294 by @OSA413)
列类型与装饰器
其他
- v1 迁移的自动化 codemod — 新增
@typeorm/codemod包,可自动处理大部分破坏性变更:运行npx @typeorm/codemod v1 src/即可更新导入、API 重命名、find 选项语法等 (#12233 by @pkuczynski) - 改进的 ormconfig 错误处理 — 加载失败现在会记录警告日志,而不是静默失败 (#11871 by @Cprakhar)
Bug 修复
查询生成
- Column alias properly escaped in
orderBy— 防止当别名名称与保留字冲突时产生 SQL 错误 (#12027 by @Cprakhar) addOrderBy解析数据库列名 — 使用数据库列名(例如created_at)而不是属性名现在可以正常工作 (#11904 by @smith-xyz)- Order 子查询列解析 — 修复在按子查询列进行排序时出现 “Cannot get metadata for given alias” 错误 (#11343 by @trannhan0810)
select列排序得以保留 —getQuery()/getSql()现在会以通过select()和addSelect()添加的顺序返回列 (#11902 by @Cprakhar).update()查询生成已修复 — 修正使用 QueryBuilder.update()时生成了错误的 SQL (#11993 by @gioboa)- 带表别名的 Upsert SQL 生成 — 修复对具有表继承和自定义 schema 的 upsert 查询中错误的列引用 (#11915 by @Cprakhar)
- 带连接的 Limit — 修复在使用带连接的
skip/take分页时出现不正确结果的问题 (#11987 by @gioboa) - 方括号内的 Join 属性 — 当条件中包含方括号时,修复了 join 解析问题 (#11218 by @balkrushna)
- 禁用聚合函数的全局
ORDER BY—repo.max()、repo.min()等现在不再在带ORDER BY子句时生成无效 SQL (#11925 by @Cprakhar) - 分页子查询包含已连接实体的 PK — 使用
leftJoin搭配skip/take现在会正确加载关联实体 (#11669 by @mag123c) - 驼峰命名的别名缩短 —
shorten方法现在能正确处理camelCase_aliases(#11283 by @OSA413) QueryBuilder.update()的实体类型 —update(partialEntity)签名现在使用了正确的实体感知类型,而不是松散的对象类型 (#11296 by @OSA413)- 记录查询的空白处理 — 日志中的查询字符串不再包含尾部和头部的空白字符 (#12047 by @Cprakhar)
关系与贪婪加载
- 非可空 FK 的孤儿一对多子项现在会被删除 — 当保存一个带级联的一对多关系并替换子项时,具有非可空 FK 的孤儿行现在会被删除,而不是因约束违规而失败;可空 FK 行仍如之前一样被置为 null (#11982 by @naorpeled)
- 急加载关系现在会尊重
relationLoadStrategy: "query"— 当设置"query"策略时,急加载关系通过独立查询加载,而不是始终使用 JOIN (#11326 by @SharkSharp, #12256 by @pkuczynski) - 自引用关系别名冲突 — 当
relationLoadStrategy: "query"用于自引用关系时,不再因别名冲突产生错误 SQL (#11066 by @campmarc) - 急加载关系不再重复 JOIN — 在
relations中显式指定急加载关系不再导致重复的 JOIN (#11991 by @veeceey) - 带急加载关系的保存 — 修复当实体具有急加载关系时保存失败的问题 (#11975 by @gioboa)
select: false的列不再被返回 — 标记为select: false的列现在会正确地从查询结果中排除 (#11944 by @gioboa)- 使用
joinMapOne方法的子查询 — 修复使用 join map 方法时的错误行为 (#11943 by @gioboa) - 嵌套嵌入实体中的 Relation IDs — 当在嵌入实体中映射 relation ids 时,修复
TypeError: Cannot set properties of undefined(#11942 by @Cprakhar) RelationIdLoader的别名处理 — 使用DriverUtils.getAlias以防止具有较短标识符限制的数据库进行别名截断 (#11228 by @te1)createPropertyPath中的*-to-many— 移除了阻止某些关系配置的错误处理 (#11119 by @ThbltLmr)- 复合主键上的
OneToMany级联删除 — 当目标具有复合 PK 时,cascade: ["remove"]现在会正确地将删除操作传播到子实体;之前CascadesSubjectBuilder从未将这些子实体标记为mustBeRemoved,从而导致 FK 约束违规 (#12286 by @pkuczynski) - 用于多对多恢复时将
withDeleted传播给 relation-id loader — 使用多对多关系恢复已软删除的实体时,不再尝试重新插入已有的连接表行;当父查询设置了withDeleted时,RelationIdLoader现在会包含软删除的实体 (#12287 by @pkuczynski)
持久化
update: false或generatedType的 upsert — upsert 现在能正确处理那些不应更新的列 (#12030 by @gioboa)- 对
FindOperator应用值转换器 —ApplyValueTransformers现在会正确转换FindOperator实例内部的值,例如In、Between等 (#11172 by @ZimGil) - 软删除不再更新已软删除的行 —
softDelete和softRemove现在会跳过已经软删除的行 (#10705 by @hassanmehdi98) - 实体合并尊重
null值 — 合并到实体时不再静默丢弃null属性值 (#11154 by @knoid) - Map/对象比较 — 修复 Map 和普通对象列值的错误变更检测 (#10990 by @mgohin)
- 日期转换器变更检测 — 修复带日期值转换器时的错误阳性脏数据检测 (#11963 by @gioboa)
- 子 mpath 更新 — 当重新挂载树形实体的父项时,即使父项是软删除的,tree entity 的 mpath 也会被正确更新 (#10844 by @JoseCToscano)
- Closure 连接表的 schema/database 传播 — schema 和 database 设置现在会被正确传播到 closure 连接表 (#12110 by @pkuczynski)
- schema builder 中对虚拟属性的处理 — schema builder 不再尝试为虚拟属性创建列 (#11000 by @skyran1278)
- 未命名的
TableForeignKey删除 — 删除未显式指定名称的外键不再失败 (#10744 by @taichunmin) getPendingMigrations不再创建迁移表 — 检查待执行迁移不再产生副作用 (#11672 by @pkuczynski)- 多对多
deferrable外键 —@ManyToMany现在会在连接表的外键上遵从deferrable选项 (#11924 by @smith-xyz) - 复合外键列顺序 — schema builder 会对复合外键中被引用的列进行排序,以匹配被引用的主键索引顺序,从而避免 MySQL / MSSQL / SAP HANA 拒绝约束 (#12280 by @pkuczynski)
驱动特定修复
- PostgreSQL:
timestamptz持久化/填充 —timestamp with time zone列现在能正确持久化和填充 (#11774 by @Minishlink) - PostgreSQL:几何类型重新保存 — 在持久化时会对 point/circle 值进行规范化,以避免重新保存填充对象时出现无效输入错误 (#11857 by @Cprakhar)
- PostgreSQL/CockroachDB:带引号的表名 — 修复了对名称中包含特殊字符的表的处理问题 (#10993 by @iskalyakin)
- PostgreSQL:顺序查询执行 — 现在在同一连接上顺序执行查询,以避免
pg8.19.0 弃用警告 (#12105 by @pkuczynski) - MySQL:PolarDB-X 2.0 版本检测 —
getVersion()不再为 PolarDB-X 2.0 返回undefined(#11837 by @Missna) - MongoDB:
ObjectIdColumn属性名转换 —findOneBy({ id: value })现在能正确转换为 MongoDB 查询中的_id(#12200 by @pkuczynski) - MongoDB:嵌套文档中的嵌入数组 — 正确处理嵌套文档结构中的嵌入数组 (#10940 by @mciuchitu)
- SQLite:simple-enum 数组 — 带
array: true的simple-enum列不再因 CHECK 约束错误而失败 (#11865 by @Cprakhar) - SAP HANA:
Date参数转义 — JSDate值现在作为查询参数传递,而不是嵌入到 SQL 字符串中 (#11867 by @alumni) - CockroachDB:事务重试中的结构化查询结果 —
useStructuredResult标志现在在 CockroachDB 事务重试回放期间得以保留 (#11861 by @naorpeled) - Cordova:查询受影响行数 — 查询结果现在包含受影响行的计数 (#10873 by @jacobg)
其他
- CLI
init命令 — 当package.json不存在时不再崩溃 (#11947 by @gioboa);发布的包现在正确包含了脚手架所需的devDependencies(#12281 by @pkuczynski) - Deno
process导入 — 修复了 Deno 上process依赖的错误导入问题 (#11248 by @yohannpoli)
安全修复
- SQL injection prevention — 现在在所有驱动中,schema introspection 和 DDL 方法都使用参数化查询和已转义的标识符,从而防止通过 database/schema/table/column 名称进行 SQL 注入 (#12207 by @pkuczynski, #12197 by @pkuczynski, #12185 by @pkuczynski)
- OrderBy condition validation — QueryBuilder
orderBy和addOrderBy现在会在运行时验证 condition 值,防止通过 order expressions 进行注入 (#12217 by @pkuczynski)
性能改进
- PostgreSQL / CockroachDB:
clearDatabase()中的批量 DROP — 将单独的 DROP 语句合并为单个批量查询,显著减少测试设置期间的往返次数(#12164, #12159 由 @pkuczynski 贡献)