跳至主内容区

迁移到 v1 版本

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

本文是从 0.3.x 版本升级到 1.0 的迁移指南。

平台要求

Node.js 20+

最低 JavaScript 编译目标已提升至 ES2023,这要求 Node.js 20 或更高版本。若仍在使用旧版 Node.js,请先升级再更新 TypeORM。

非 Node 平台中 Buffer 替换为 Uint8Array

浏览器端 Buffer polyfill 已被移除。在非 Node 平台(浏览器/Deno/Bun)中,二进制数据现统一用 Uint8Array 表示。Node.js 用户不受影响——Node 的 Buffer 继承自 Uint8Array 且行为保持不变。

驱动变更

MySQL / MariaDB

移除 connectorPackage 配置项

connectorPackage 配置项已被移除,同时停止支持旧版 mysql 客户端。目前唯一支持的数据库客户端是 mysql2,TypeORM 将默认尝试加载该驱动。若您项目中正在使用 mysql,请直接替换为 mysql2

legacySpatialSupport 默认值改为 false

legacySpatialSupport 选项现在默认为 false,这意味着 TypeORM 将使用符合标准的空间函数 ST_GeomFromTextST_AsText(这些函数在 MySQL 5.7 中引入,且为 MySQL 8.0+ 所必需)。旧版的 GeomFromTextAsText 函数已在 MySQL 8.0 中移除。

若你正在运行 MySQL 5.6 或更早版本并依赖空间类型,请显式设置 legacySpatialSupport: true

new DataSource({
type: "mysql",
legacySpatialSupport: true,
// ...
})

移除 widthzerofill 列选项

MySQL 8.0.17 弃用了整数类型的显示宽度和 ZEROFILL 属性,而 MySQL 8.4 则完全移除了它们。因此 TypeORM 不再支持 widthzerofill 列选项。若你曾使用这些选项,请从列定义中移除:

// Before
@Column({ type: "int", width: 9, zerofill: true })
postCode: number

// After
@Column({ type: "int" })
postCode: number

如需零填充显示格式,请在应用层使用 String.prototype.padStart() 或在原生查询中用 MySQL 的 LPAD() 函数处理。整数类型的 unsigned 选项不受此变更影响。

SQLite

已停止支持 sqlite3 包,请改用 better-sqlite3

// Before
new DataSource({
type: "sqlite",
database: "db.sqlite",
})

// After
new DataSource({
type: "better-sqlite3",
database: "db.sqlite",
})

移除 flags 配置项

sqlite3 包曾接受 C 级别的打开标志(如 OPEN_URIOPEN_SHAREDCACHE 等)。better-sqlite3 不支持此方式,请改用以下专用配置项:

  • readonly:用于只读模式

  • enableWAL:用于启用 WAL 日志模式

busyTimeout 配置项更名为 timeout

sqlite3 包使用 busyTimeout 配置 SQLite 的忙等待超时,而 better-sqlite3 改用 timeout(默认值:5000毫秒):

// Before
new DataSource({
type: "sqlite",
database: "db.sqlite",
busyTimeout: 2000,
})

// After
new DataSource({
type: "better-sqlite3",
database: "db.sqlite",
timeout: 2000,
})

MongoDB

TypeORM 现在要求 mongodb Node.js 驱动版本为 v7 或更高(即 ^7.0.0),已停止支持 mongodb 驱动的 v5/v6 版本。

移除已弃用的连接选项

以下 MongoDB 连接选项已被移除:

Removed optionAction
appnameUse appName (camelCase) instead
fsyncUse writeConcern: { journal: true } instead
jUse writeConcern: { journal: true } instead
keepAliveRemove — always enabled since MongoDB Driver v6.0
keepAliveInitialDelayRemove — not configurable since MongoDB Driver v6.0
sslUse tls instead
sslCAUse tlsCAFile instead
sslCRLRemove — no replacement in modern driver
sslCertUse tlsCertificateKeyFile instead
sslKeyUse tlsCertificateKeyFile instead
sslPassUse tlsCertificateKeyFilePassword instead
sslValidateUse tlsAllowInvalidCertificates (inverted) instead
useNewUrlParserRemove — no-op since MongoDB Driver v4.0
useUnifiedTopologyRemove — no-op since MongoDB Driver v4.0
wUse writeConcern: { w: 1 } instead
wtimeoutUse writeConcern: { wtimeoutMS: 2500 } instead
wtimeoutMSUse writeConcern: { wtimeoutMS: 2500 } instead

移除 stats() 方法

stats() 方法已从 MongoQueryRunnerMongoEntityManagerMongoRepository 中移除。底层的 collStats 命令已在 MongoDB 服务器 6.2 中弃用,而 Collection.stats() 方法则在 MongoDB 驱动 v7 中被移除。

请改用 $collStats 聚合阶段。请注意响应结构已变化——countsizestorageSize 等属性现在嵌套在 storageStats 下,而非顶层。

// Before
const stats = await mongoRepository.stats()
console.log(stats.count)
console.log(stats.size)
console.log(stats.totalIndexSize)

// After — use $collStats aggregation stage
const [stats] = await dataSource.mongoManager
.aggregate(MyEntity, [{ $collStats: { storageStats: {} } }])
.toArray()
console.log(stats.storageStats.count)
console.log(stats.storageStats.size)
console.log(stats.storageStats.totalIndexSize)

移除全局函数 getMongoRepositorygetMongoManager

已弃用的全局函数 getMongoRepository()getMongoManager() 已被移除。请改用 DataSourceEntityManager 上的对应实例方法:

// Before
import { getMongoManager, getMongoRepository } from "typeorm"

const manager = getMongoManager()
const repository = getMongoRepository(User)

// After
const manager = dataSource.mongoManager
const repository = dataSource.getMongoRepository(User)

类型声明

内部 MongoDB 类型(如 ObjectId)不再从 typeorm 重新导出,请直接从 mongodb 导入:

// Before
import { ObjectId } from "typeorm"

// After
import { ObjectId } from "mongodb"

MS SQL Server

移除 domain 连接选项

SqlServerConnectionCredentialsOptions 中已弃用的 domain 配置项已被移除。请改用带有 NTLM 类型的 authentication 配置项:

// Before
new DataSource({
type: "mssql",
domain: "MYDOMAIN",
username: "user",
password: "pass",
// ...
})

// After
new DataSource({
type: "mssql",
authentication: {
type: "ntlm",
options: {
domain: "MYDOMAIN",
userName: "user",
password: "pass",
},
},
// ...
})

SAP HANA

多个已弃用的 SAP HANA 连接别名已被移除。

  • hanaClientDriver 已被移除,请改用 driver

  • pool.max 已被移除,请改用 pool.maxConnectedOrPooled

  • pool.requestTimeout 已被移除,请改用 pool.maxWaitTimeoutIfPoolExhausted

  • pool.idleTimeout 已被移除,请改用 pool.maxPooledIdleTime(单位为秒)

  • pool.minpool.maxWaitingRequestspool.checkInterval 已被移除,且无替代项

另请注意连接池配置的默认行为变更:

  • pool.maxPooledIdleTime 现在默认为 30 秒,且不再回退至 pool.idleTimeout

  • pool.maxWaitTimeoutIfPoolExhausted 现在默认为 0,且不再回退至 pool.requestTimeout

Expo

已移除对旧版 Expo SQLite 驱动的支持。Expo 在 SDK v52 中移除了旧版 API,请升级至 Expo SDK v52 或更高版本并使用现代异步 SQLite API:

// Before
new DataSource({
type: "expo",
database: "db.sqlite",
})

// After — use Expo SDK v52+ with the modern async API
new DataSource({
type: "expo",
database: "db.sqlite",
driver: require("expo-sqlite"),
})

Redis(缓存)

RedisQueryResultCache 中已移除对旧版(v3)Redis 客户端的支持,请升级至 Redis 客户端 v4 或更高版本redis/ioredis):

// Before — redis v3
import { createClient } from "redis"
const client = createClient()

// After — redis v4+
import { createClient } from "redis"
const client = createClient()
await client.connect()

数据源(DataSource)

ConnectionDataSource

DataSource 在 v0.3 已取代 Connection,现完全移除向后兼容别名:

// Before
import { Connection, ConnectionOptions } from "typeorm"

const connection = await createConnection(options)
await connection.close()

// After
import { DataSource, DataSourceOptions } from "typeorm"

const dataSource = new DataSource(options)
await dataSource.initialize()
await dataSource.destroy()

以下全局重命名生效:

BeforeAfter
ConnectionDataSource
ConnectionOptionsDataSourceOptions
BaseConnectionOptionsBaseDataSourceOptions
MysqlConnectionOptionsMysqlDataSourceOptions
(same pattern for all drivers)
connection.connect()dataSource.initialize()
connection.close()dataSource.destroy()
connection.isConnecteddataSource.isInitialized

移除 name 属性

DataSourceBaseDataSourceOptions 中已弃用的 name 属性已被移除。命名连接在 v0.3 版本移除 ConnectionManager 时已被弃用。若需使用 name 来标识连接,请直接管理 DataSource 实例。

注意:读取 dataSource.name 的代码现在会得到 undefined(原为 "default")。若在日志或多租户逻辑中使用该值,请相应调整。

各类中的 .connection 属性现已更名为 .dataSource

DriverQueryRunnerEntityManagerQueryBuilderEntityMetadata*Event 类中,connection 属性已重命名为 dataSource。对于 EntityManager,此变更在 0.3 版本已预告但未实际实施。为简化迁移,已添加一个返回与 dataSource 相同值的弃用 getter。

其他变更

ConnectionManager 类已被移除。若您曾用它管理多个连接,请直接创建并管理 DataSource 实例。

ConnectionOptionsReader 也已简化:all() 重命名为 get()(以数组形式返回所有配置),旧版 get(name)has(name) 方法被移除。

const reader = new ConnectionOptionsReader()

// when your ormconfig has a single data source
const [options] = await reader.get()

// when you need a specific config from multiple data sources
const allOptions = await reader.get()
const postgresOptions = allOptions.find((o) => o.type === "postgres")

移除全局快捷函数

以下已弃用的全局函数已被移除:

  • createConnection / createConnections

  • getConnection

  • getConnectionManager

  • getConnectionOptions

  • getManager

  • getSqljsManager

  • getRepository

  • getTreeRepository

  • createQueryBuilder

请改用 DataSource 实例的等效方法:

// Before
const repo = getRepository(User)
const qb = createQueryBuilder("user")

// After
const repo = dataSource.getRepository(User)
const qb = dataSource.createQueryBuilder("user")

环境变量配置功能已移除

已弃用的 ConnectionOptionsEnvReader 类及通过 TYPEORM_CONNECTIONTYPEORM_URLTYPEORM_* 环境变量配置连接的功能已被移除。同时不再支持 ormconfig.env 文件格式。TypeORM 不再自动加载 .env 文件或依赖 dotenv

请改用 TypeScript 或 JavaScript 配置文件:

// ormconfig.ts
export default {
type: process.env.DB_TYPE,
url: process.env.DB_URL,
// ...
}

行为变更

invalidWhereValuesBehavior 默认值更改为 throw

这是一项重大行为变更,可能导致现有应用在运行时中断。

WHERE 条件中 null 和 undefined 值的默认处理行为已变更。此前这些值会被静默忽略(跳过对应属性),现在默认情况下两者都会抛出错误

此项变更修复了 findBy({ id: undefined }) 类查询会静默返回所有行而非报错的潜在缺陷。

// v0.3: silently returns all posts (null is ignored)
// v1.0: throws TypeORMError
await repository.find({ where: { text: null } })

// v0.3: silently returns all posts (undefined is ignored)
// v1.0: throws TypeORMError
await repository.find({ where: { text: undefined } })

若需匹配 null 值,请使用 IsNull() 操作符:

import { IsNull } from "typeorm"

await repository.find({ where: { text: IsNull() } })

要恢复旧版行为,请在数据源配置中设置 invalidWhereValuesBehavior

new DataSource({
// ...
invalidWhereValuesBehavior: {
null: "ignore",
undefined: "ignore",
},
})

此设置作用于所有高级 API —— 包括查找操作、仓库/管理器变更方法及 queryBuilder.setFindOptions()(唯一受影响的 QueryBuilder 方法)。其余 QueryBuilder 方法(.where().andWhere().orWhere()不受影响 —— null 和 undefined 值会原样传递。完整说明请参阅 空值与未定义处理

哈希算法

TypeORM 此前使用 sha.js npm 包进行 SHA-1 哈希计算(非标准实现)。现改为使用 Node.js 内置的 crypto 模块,同时 uuid 包已被 crypto.randomUUID() 替代。

在浏览器环境中,RandomGenerator.sha1 已修正为标准实现。

影响: 若您使用 TypeORM 的查询结果缓存,升级后现有缓存条目将失效,因为哈希函数输出结果已改变。此变更无害——缓存将自动重建——但短期内可能观察到缓存命中率下降。

通配符模式

通配符模式(用于实体/迁移文件发现)现由 tinyglobby 替代 glob 处理。基本功能保持一致,但涉及大括号扩展或平台特定路径分隔符的边缘情况可能表现不同。

列(Columns)

readonly 选项已移除

已弃用的 readonly 列选项已被移除。请改用 update 选项——注意它接受相反的值:

// Before
@Column({ readonly: true })
authorName: string

// After
@Column({ update: false })
authorName: string

ColumnNumericOptions 中的 unsigned 已移除

ColumnNumericOptions 中已弃用的 unsigned 属性(用于 @Column("decimal", { unsigned: true }) 等小数/浮点列类型重载)已被移除,因 MySQL 已弃用非整数数值类型的 UNSIGNED。整数类型 ColumnOptions 中的 unsigned 选项 不受 影响。

关联关系

nullable: false 现在使用 INNER JOIN

标记为 nullable: false 的关联关系现在通过 relations、贪婪加载或查询选项加载时,会使用 INNER JOIN 而非 LEFT JOIN。此变更仅适用于拥有连接列的关联类型(ManyToOne 和拥有方的 OneToOne)。

这在语义上是正确的,因为非空外键保证了相关实体必然存在,且允许数据库优化器生成更高效的查询计划。

潜在破坏性变更: 若数据库中存在违反 NOT NULL 约束的行(例如孤儿外键,或设置了 nullable: false 但数据库列实际可为空),这些行将被排除在查询结果之外。请验证数据完整性,或根据需要将关联关系改为 nullable: true

// INNER JOIN — related entity is guaranteed to exist
@ManyToOne(() => User, { nullable: false })
author: User

// LEFT JOIN — related entity may not exist (default)
@ManyToOne(() => User)
optionalEditor: User

OneToManyManyToMany 和反向 OneToOne 关系始终使用 LEFT JOIN(无论 nullable 设置如何),因为这些关联类型在当前表上没有连接列。

软删除例外: 若关联实体包含 @DeleteDateColumn,即使对于 nullable: false 的关系也会使用 LEFT JOIN(除非显式设置 withDeleted: true)。这能防止软删除的关联实体过滤掉其父行。

仓储(Repository)

findOneById

已弃用的 findOneById 方法已从 EntityManagerRepositoryBaseEntityMongoEntityManagerMongoRepository 中移除。请改用 findOneBy

// Before
const user = await manager.findOneById(User, 1)
const user = await repository.findOneById(1)
const user = await User.findOneById(1)

// After
const user = await manager.findOneBy(User, { id: 1 })
const user = await repository.findOneBy({ id: 1 })
const user = await User.findOneBy({ id: 1 })

对于使用 @ObjectIdColumn() 的 MongoDB 实体,findOneBy 工作方式相同——TypeORM 会自动将属性名转换为 _id

findByIds 已移除

EntityManagerRepositoryBaseEntity 中已弃用的 findByIds 方法已被移除。请改用 findBy 配合 In 操作符:

// Before
const users = await repository.findByIds([1, 2, 3])

// After
import { In } from "typeorm"

const users = await repository.findBy({ id: In([1, 2, 3]) })

exist 更名为 exists

已弃用的 Repository.exist() 方法已被移除。请改用 exists()——两者行为完全一致:

// Before
const hasUsers = await userRepository.exist({ where: { isActive: true } })

// After
const hasUsers = await userRepository.exists({ where: { isActive: true } })

AbstractRepository@EntityRepositorygetCustomRepository 已移除

AbstractRepository 类、@EntityRepository 装饰器和 getCustomRepository() 方法已被移除。这些功能在 v0.3 中已被弃用,推荐使用 Repository.extend()

// Before
@EntityRepository(User)
class UserRepository extends AbstractRepository<User> {
findByName(name: string) {
return this.repository.findOneBy({ name })
}
}
const userRepo = dataSource.getCustomRepository(UserRepository)

// After
const UserRepository = dataSource.getRepository(User).extend({
findByName(name: string) {
return this.findOneBy({ name })
},
})

以下错误类也被移除:CustomRepositoryDoesNotHaveEntityErrorCustomRepositoryCannotInheritRepositoryErrorCustomRepositoryNotFoundError

@RelationCount 装饰器和 loadRelationCountAndMap 已移除

@RelationCount 装饰器和 SelectQueryBuilder.loadRelationCountAndMap() 方法已被移除。请改用 @VirtualColumn 或在查询构建器中使用子查询:

// Before
@RelationCount((post: Post) => post.categories)
categoryCount: number

// After — use @VirtualColumn with a sub-query
// Replace the junction table name and column names to match your schema
@VirtualColumn({
query: (alias) =>
`SELECT COUNT(*) FROM post_categories_category WHERE postId = ${alias}.id`,
})
categoryCount: number

查询选项

移除 join 选项

已弃用的 FindOneOptionsFindManyOptions 中的 join 属性及 JoinOptions 接口已被移除。

leftJoinAndSelectrelations

若曾使用 leftJoinAndSelect,请改用 relations 的对象语法——relations 始终执行带结果选择的 LEFT JOIN,效果等同:

// Before
const posts = await repository.find({
join: {
alias: "post",
leftJoinAndSelect: {
categories: "post.categories",
author: "post.author",
},
},
})

// After
const posts = await repository.find({
relations: { categories: true, author: true },
})

其他 JOIN 类型 → 改用 QueryBuilder

relations 选项仅支持带结果选择的 LEFT JOIN。若曾使用 innerJoinAndSelectinnerJoinleftJoin(不带选择),请切换到 QueryBuilder API:

// Before — innerJoinAndSelect
const posts = await repository.find({
join: {
alias: "post",
innerJoinAndSelect: {
categories: "post.categories",
},
},
})

// After — QueryBuilder with innerJoinAndSelect
const posts = await repository
.createQueryBuilder("post")
.innerJoinAndSelect("post.categories", "categories")
.getMany()

// Before — leftJoin (without select)
const posts = await repository.find({
join: {
alias: "post",
leftJoin: {
categories: "post.categories",
},
},
where: { categories: { isRemoved: false } },
})

// After — QueryBuilder with leftJoin
const posts = await repository
.createQueryBuilder("post")
.leftJoin("post.categories", "categories")
.where("categories.isRemoved = :isRemoved", { isRemoved: false })
.getMany()

此区别在实际中很重要。例如 PostgreSQL 和 CockroachDB 不允许在外部连接的可空侧使用 FOR UPDATE,因此结合锁操作与关联加载的查询可能需要 INNER JOIN:

// Before — innerJoinAndSelect + lock
const post = await repository.findOne({
join: {
alias: "post",
innerJoinAndSelect: {
categories: "post.categories",
},
},
lock: { mode: "pessimistic_write", tables: ["category"] },
})

// After — QueryBuilder with innerJoinAndSelect + lock
const post = await repository
.createQueryBuilder("post")
.innerJoinAndSelect("post.categories", "categories")
.setLock("pessimistic_write", undefined, ["categories"])
.getOne()

嵌套关联的锁操作 → 改用 QueryBuilder

relations 选项无法在连接表上使用悲观锁,因为 relations 始终使用 LEFT JOIN,而 PostgreSQL/CockroachDB 会拒绝在外部连接的可空侧使用 FOR UPDATE。请改用带 innerJoinAndSelect 的 QueryBuilder:

// Before — nested relations + lock via find options
const post = await repository.findOne({
where: { id: 1 },
join: {
alias: "post",
innerJoinAndSelect: {
categories: "post.categories",
images: "categories.images",
},
},
lock: { mode: "pessimistic_write", tables: ["images"] },
})

// After — QueryBuilder with innerJoinAndSelect + lock
const post = await repository
.createQueryBuilder("post")
.innerJoinAndSelect("post.categories", "categories")
.innerJoinAndSelect("categories.images", "images")
.where("post.id = :id", { id: 1 })
.setLock("pessimistic_write", undefined, ["images"])
.getOne()

注意锁定_主表_仍可通过 relations 实现——仅锁定_关联表_时才需使用带内连接的 QueryBuilder。

基于字符串的 select 已移除

已弃用的 select 查询选项字符串数组语法已被移除,请改用对象语法:

// Before
const users = await repository.find({
select: ["id", "name"],
})

// After
const users = await repository.find({
select: { id: true, name: true },
})

被移除的类型是 FindOptionsSelectByString

基于字符串的 relations 已移除

已弃用的 relations 查询选项字符串数组语法已被移除,请改用对象语法:

// Before
const users = await repository.find({
relations: ["profile", "posts"],
})

// After
const users = await repository.find({
relations: { profile: true, posts: true },
})

被移除的类型是 FindOptionsRelationByString

查询构建器(QueryBuilder)

移除 printSql

查询构建器上的 printSql() 方法已被移除。该方法冗余,因为当启用查询日志时,所有执行过的查询都会通过配置的记录器自动记录。请改用 getSql()getQueryAndParameters() 来检查生成的 SQL:

// Before
const users = await dataSource
.getRepository(User)
.createQueryBuilder("user")
.where("user.id = :id", { id: 1 })
.printSql()
.getMany()

// After — inspect SQL before executing
const qb = dataSource
.getRepository(User)
.createQueryBuilder("user")
.where("user.id = :id", { id: 1 })

console.log(qb.getSql())
// or: const [sql, params] = qb.getQueryAndParameters()

const users = await qb.getMany()

要自动记录所有执行的查询,请在 DataSource 中启用查询日志:

new DataSource({
// ...
logging: ["query"],
})

onConflict 已移除

InsertQueryBuilder 上的 onConflict() 方法已被移除。该方法接受原始 SQL 字符串,存在驱动依赖性强且易出错的问题。请改用 orIgnore()orUpdate()

// Before
await dataSource
.createQueryBuilder()
.insert()
.into(Post)
.values(post)
.onConflict(`("id") DO NOTHING`)
.execute()

// After
await dataSource
.createQueryBuilder()
.insert()
.into(Post)
.values(post)
.orIgnore()
.execute()

// Before
await dataSource
.createQueryBuilder()
.insert()
.into(Post)
.values(post)
.onConflict(`("id") DO UPDATE SET "title" = :title`)
.setParameter("title", post.title)
.execute()

// After
await dataSource
.createQueryBuilder()
.insert()
.into(Post)
.values(post)
.orUpdate(["title"], ["id"])
.execute()

orUpdate 对象重载已移除

接受对象参数 { columns?, overwrite?, conflict_target? }orUpdate() 重载已被移除。请改用数组形式的签名:

// Before
.orUpdate({ conflict_target: ["date"], overwrite: ["title"] })

// After
.orUpdate(["title"], ["date"])

setNativeParameters 已移除

// Before
qb.setNativeParameters({ key: "value" })

// After
qb.setParameters({ key: "value" })

内部属性 QueryExpressionMap.nativeParameters 也已移除。若您的自定义 QueryBuilder 子类访问了 expressionMap.nativeParameters,请改用 expressionMap.parameters

WhereExpression 类型别名已移除

// Before
import { WhereExpression } from "typeorm"

// After
import { WhereExpressionBuilder } from "typeorm"

replacePropertyNames 已移除

已弃用的受保护方法 replacePropertyNames() 已被移除。由于属性名替换已通过 replacePropertyNamesForTheWholeQuery() 移至查询结束阶段处理,该方法实际已成为空操作。若您在自定义 QueryBuilder 子类中覆盖此方法,该覆盖将不再生效。

已弃用的锁模式已移除

// Before
.setLock("pessimistic_partial_write")

// After
.setLock("pessimistic_write")
.setOnLocked("skip_locked")

// Before
.setLock("pessimistic_write_or_fail")

// After
.setLock("pessimistic_write")
.setOnLocked("nowait")

查找选项同理:

// Before
{ lock: { mode: "pessimistic_partial_write" } }

// After
{ lock: { mode: "pessimistic_write", onLocked: "skip_locked" } }

// Before
{ lock: { mode: "pessimistic_write_or_fail" } }

// After
{ lock: { mode: "pessimistic_write", onLocked: "nowait" } }

迁移功能变更

getAllMigrations 已移除

MigrationExecutor 中已弃用的 getAllMigrations() 方法已被移除。请改用 getPendingMigrations()getExecutedMigrations(),或直接访问 dataSource.migrations 获取注册的迁移类列表:

// Before
const migrations = await migrationExecutor.getAllMigrations()

// After — depending on what you need
const pending = await migrationExecutor.getPendingMigrations()
const executed = await migrationExecutor.getExecutedMigrations()
const registered = dataSource.migrations

QueryRunner.loadedTablesloadedViews 已移除

// Before
const tables = queryRunner.loadedTables
const views = queryRunner.loadedViews

// After
const tables = await queryRunner.getTables()
const views = await queryRunner.getViews()

注意:替代方案为异步方法,而非同步属性。

容器系统

已弃用的 IoC 容器集成已被移除,包括:useContainer()getFromContainer()ContainerInterfaceContainedTypeUseContainerOptions

TypeORM 不再内置支持 IoC 容器。typeorm-typedi-extensionstypeorm-routing-controllers-extensions 包也不再兼容。以下部分将根据你的配置介绍迁移方法。

带依赖项的订阅器和迁移

TypeORM 始终通过无参构造函数在内部实例化订阅者和迁移,因此无法传递预构建实例。若迁移需要访问服务,请在迁移内部使用 DataSource(可通过 queryRunner.dataSource 获取):

// Before
import { useContainer } from "typeorm"
import { Container } from "typedi"
useContainer(Container)

// After — access dependencies via the DataSource inside the migration
export class MyMigration1234 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
const repo = queryRunner.dataSource.getRepository(User)
// ...
}
}

访问存储库和实体管理器

如果你之前使用 typeorm-typedi-extensionsEntityManager 或存储库注入到服务中,现在请直接使用 DataSource

// Before (with typeorm-typedi-extensions)
import { InjectManager, InjectRepository } from "typeorm-typedi-extensions"

class UserService {
@InjectManager()
private manager: EntityManager

@InjectRepository(User)
private userRepository: Repository<User>
}

// After — access from the DataSource instance
class UserService {
private manager: EntityManager
private userRepository: Repository<User>

constructor(dataSource: DataSource) {
this.manager = dataSource.manager
this.userRepository = dataSource.getRepository(User)
}
}

与 DI 框架配合使用

如果使用 DI 框架,请将 DataSource(或其存储库)注册为容器中的提供者:

// typedi example
import { DataSource } from "typeorm"
import { Container } from "typedi"

const dataSource = new DataSource({
/* ... */
})
await dataSource.initialize()
Container.set(DataSource, dataSource)
Container.set("UserRepository", dataSource.getRepository(User))

NestJS

NestJS 用户不受影响——@nestjs/typeorm 包拥有独立集成方案,不依赖 TypeORM 已移除的容器系统。但请注意:@nestjs/typeorm v10 及当前 v11.0.0 会尝试注册已移除的 Connection 类,导致启动崩溃。请确保您使用的 @nestjs/typeorm 版本包含 TypeORM v1 兼容性修复。

其他内部移除项

以下内部 API 已被移除。这些变更仅影响构建自定义驱动、扩展 QueryBuilder 或使用底层元数据 API 的用户:

RemovedReplacement
EntityMetadata.createPropertyPath() (static)Removed with no public replacement
DriverUtils.buildColumnAlias()Use DriverUtils.buildAlias()
Broadcaster.broadcastLoadEventsForAll()No replacement — use individual event subscribers
QueryExpressionMap.nativeParametersUse QueryExpressionMap.parameters