跳至主内容区

在 WHERE 条件中处理 null 和 undefined 值

非官方测试版翻译

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

在 'WHERE' 条件中,nullundefined 在 TypeORM 中并非严格有效的值。

在编译时,TypeScript(当你在 tsconfig.json 中启用了 strictNullChecks)会禁止传递已知的 null 值。但默认行为是忽略运行时遇到的 null 值。同样地,undefined 值会被 TypeScript 允许并在运行时被忽略。

接受 nullundefined 值有时会导致意外结果,需要谨慎对待。当值来自用户输入且未经充分验证时,这一点尤其值得注意。

例如,调用 Repository.findOneBy({ id: undefined }) 会返回表中的第一行,而 Repository.findBy({ userId: null }) 则不会进行过滤,会返回所有行。

可以通过数据源选项中的 invalidWhereValuesBehavior 配置项来自定义 nullundefined 值的处理方式。这适用于所有支持 'WHERE' 条件的操作,包括查找操作、查询构建器和存储库方法。

备注

当前行为在 TypeORM 的未来版本中将会更改, 我们建议将 nullundefined 的行为都设置为 'throw' 以准备这些更改

默认行为

默认情况下,TypeORM 在 WHERE 条件中会跳过 nullundefined 值。这意味着,如果你在 WHERE 子句中包含值为 nullundefined 的属性,该属性将被忽略:

// Both queries will return all posts, ignoring the text property
const posts1 = await repository.find({
where: {
text: null,
},
})

const posts2 = await repository.find({
where: {
text: undefined,
},
})

在 WHERE 条件中匹配 null 值的正确方法是使用 IsNull 操作符(详情请参见 Find Options):

const posts = await repository.find({
where: {
text: IsNull(),
},
})

配置

你可以通过连接配置中的 invalidWhereValuesBehavior 选项来自定义 null 和 undefined 值的处理方式:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "ignore" | "sql-null" | "throw",
undefined: "ignore" | "throw",
},
})

Null 行为选项

null 行为可以设置为以下三个值之一:

'ignore'(默认)

WHERE 条件中的 JavaScript null 值会被忽略,该属性会被跳过:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "ignore",
},
})

// This will return all posts, ignoring the text property
const posts = await repository.find({
where: {
text: null,
},
})

'sql-null'

JavaScript null 值会被转换为 SQL NULL 条件:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
},
})

// This will only return posts where the text column is NULL in the database
const posts = await repository.find({
where: {
text: null,
},
})

'throw'

JavaScript null 值会导致抛出 TypeORMError:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "throw",
},
})

// This will throw an error
const posts = await repository.find({
where: {
text: null,
},
})
// Error: Null value encountered in property 'text' of a where condition.
// To match with SQL NULL, the IsNull() operator must be used.
// Set 'invalidWhereValuesBehavior.null' to 'ignore' or 'sql-null' in connection options to skip or handle null values.

Undefined 行为选项

undefined 行为可以设置为以下两个值之一:

'ignore'(默认)

WHERE 条件中的 JavaScript undefined 值会被忽略,该属性会被跳过:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
undefined: "ignore",
},
})

// This will return all posts, ignoring the text property
const posts = await repository.find({
where: {
text: undefined,
},
})

'throw'

JavaScript undefined 值会导致抛出 TypeORMError:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
undefined: "throw",
},
})

// This will throw an error
const posts = await repository.find({
where: {
text: undefined,
},
})
// Error: Undefined value encountered in property 'text' of a where condition.
// Set 'invalidWhereValuesBehavior.undefined' to 'ignore' in connection options to skip properties with undefined values.

请注意,这仅适用于显式设置的 undefined 值,不适用于省略的属性。

同时使用两个选项

你可以独立配置这两种行为以实现全面控制:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
undefined: "throw",
},
})

此配置将:

  1. 将 WHERE 条件中的 JavaScript null 值转换为 SQL NULL

  2. 遇到任何 undefined 值时抛出错误

  3. 仍然忽略 WHERE 子句中未提供的属性

这种组合在以下场景特别有用:

  • 明确地在数据库中搜索 NULL 值

  • 捕获可能潜入查询的 undefined 值导致的潜在编程错误

适用于所有 WHERE 操作

invalidWhereValuesBehavior 配置适用于所有支持 WHERE 条件的 TypeORM 操作,而不仅仅是存储库的查找方法:

查询构建器

// UpdateQueryBuilder
await dataSource
.createQueryBuilder()
.update(Post)
.set({ title: "Updated" })
.where({ text: null }) // Respects invalidWhereValuesBehavior
.execute()

// DeleteQueryBuilder
await dataSource
.createQueryBuilder()
.delete()
.from(Post)
.where({ text: null }) // Respects invalidWhereValuesBehavior
.execute()

// SoftDeleteQueryBuilder
await dataSource
.createQueryBuilder()
.softDelete()
.from(Post)
.where({ text: null }) // Respects invalidWhereValuesBehavior
.execute()

存储库方法

// Repository.update()
await repository.update({ text: null }, { title: "Updated" }) // Respects invalidWhereValuesBehavior

// Repository.delete()
await repository.delete({ text: null }) // Respects invalidWhereValuesBehavior

// EntityManager.update()
await manager.update(Post, { text: null }, { title: "Updated" }) // Respects invalidWhereValuesBehavior

// EntityManager.delete()
await manager.delete(Post, { text: null }) // Respects invalidWhereValuesBehavior

// EntityManager.softDelete()
await manager.softDelete(Post, { text: null }) // Respects invalidWhereValuesBehavior

所有这些操作都将一致应用您配置的 invalidWhereValuesBehavior 设置。