Перейти к основному содержанию

Обработка значений null и undefined в условиях WHERE

Неофициальный Бета-перевод

Эта страница переведена PageTurner AI (бета). Не одобрена официально проектом. Нашли ошибку? Сообщить о проблеме →

В условиях 'WHERE' значения null и undefined не являются строго допустимыми в TypeORM.

TypeScript запрещает передачу явного значения null при компиляции (если в tsconfig.json включена опция strictNullChecks). Поведение по умолчанию при выполнении — выброс ошибки при обнаружении null или undefined в условиях.

Обработку значений null и undefined можно настроить через опцию invalidWhereValuesBehavior в конфигурации источника данных. Это применяется к высокоуровневым операциям: методам поиска, репозитория и EntityManager (update, delete, softDelete, restore).

предупреждение

Эта настройка не влияет на методы QueryBuilder .where(), .andWhere() и .orWhere(). QueryBuilder — низкоуровневый API, где null/undefined передаются "как есть". Для явной обработки null используйте оператор IsNull() или параметризованные условия.

Поведение по умолчанию

По умолчанию TypeORM выбрасывает ошибку при обнаружении null или undefined в условиях WHERE. Это предотвращает неожиданные результаты и помогает выявлять ошибки:

// Both queries will throw an error
const posts1 = await repository.find({
where: {
text: null,
},
})
// Error: Null value encountered in property 'text' of a where condition.

const posts2 = await repository.find({
where: {
text: undefined,
},
})
// Error: Undefined value encountered in property 'text' of a where condition.

Для поиска значений null используйте оператор IsNull (подробнее в Опциях поиска):

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

Настройка

Поведение при обработке значений null и undefined можно настроить с помощью опции invalidWhereValuesBehavior в конфигурации источника данных:

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

Опции поведения для null

Поведение null может принимать одно из трёх значений:

'ignore'

Значения JavaScript null в условиях WHERE игнорируются, и свойство пропускается:

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 data source options to skip or handle null values.

Опции поведения для undefined

Поведение undefined может принимать одно из двух значений:

'ignore'

Значения JavaScript undefined в условиях WHERE игнорируются, и свойство пропускается:

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 data source options to skip properties with undefined values.

Это относится только к явно установленным значениям undefined, а не к отсутствующим свойствам.

Совместное использование опций

Оба поведения можно настроить независимо для полного контроля:

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

Такая конфигурация:

  1. Преобразует JavaScript null в SQL NULL в условиях WHERE

  2. Выбросит исключение при обнаружении значений undefined

  3. Будет игнорировать свойства, отсутствующие в условии WHERE

Этот подход полезен, когда требуется:

  • Явно указывать поиск значений NULL в базе данных

  • Отлавливать потенциальные ошибки программирования, при которых значения undefined могут попасть в запросы

Поддерживаемые операции

Настройка invalidWhereValuesBehavior применяется только к высокоуровневым операциям TypeORM, но не к прямому методу .where() в QueryBuilder:

Операции поиска

// Repository.find() / findOne() / findBy() / findOneBy()
await repository.find({ where: { text: null } }) // Respects invalidWhereValuesBehavior

// EntityManager.find() / findOne() / findBy() / findOneBy()
await manager.find(Post, { where: { text: null } }) // Respects invalidWhereValuesBehavior

Методы репозитория и EntityManager

// 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

QueryBuilder с setFindOptions

// setFindOptions goes through the find-options path, so it respects the setting
await dataSource
.createQueryBuilder(Post, "post")
.setFindOptions({ where: { text: null } }) // Respects invalidWhereValuesBehavior
.getMany()

Не затрагивается: QueryBuilder .where()

Методы .where(), .andWhere() и .orWhere() в QueryBuilder — низкоуровневые API и не зависят от этой настройки. Значения null и undefined передаются без изменений:

// This does NOT respect invalidWhereValuesBehavior — null passes through as-is
await dataSource
.createQueryBuilder()
.update(Post)
.set({ title: "Updated" })
.where({ text: null })
.execute()

Поведение null и undefined в QueryBuilder .where()

Поскольку QueryBuilder — низкоуровневый API, значения null и undefined не проверяются и не преобразуются. Понимание их поведения критично для избежания неожиданных результатов.

null в QueryBuilder .where()

При передаче null в объектном стиле .where() генерируется SQL-проверка на равенство NULL:

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: null })
.getMany()
// Generates: WHERE post.text = NULL

В SQL column = NULL всегда ложно — ничто не равно NULL. Этот запрос вернёт ноль результатов, что почти наверняка не ожидается. Для поиска NULL используйте оператор IsNull():

import { IsNull } from "typeorm"

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: IsNull() })
.getMany()
// Generates: WHERE post.text IS NULL

Или строковое условие:

await dataSource
.createQueryBuilder(Post, "post")
.where("post.text IS NULL")
.getMany()

undefined в QueryBuilder .where()

При передаче undefined поведение идентично — генерируется WHERE column = NULL, что всегда ложно:

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: undefined })
.getMany()
// Generates: WHERE post.text = NULL
// Returns: zero results

Сводная таблица

ValueHigh-level API (find/repository/manager)QueryBuilder .where()
null with "ignore"Property skipped — no filterWHERE col = NULL — zero results
null with "sql-null"WHERE col IS NULLWHERE col = NULL — zero results
null with "throw" (default)Throws errorWHERE col = NULL — zero results
undefined with "ignore"Property skipped — no filterWHERE col = NULL — zero results
undefined with "throw" (default)Throws errorWHERE col = NULL — zero results
IsNull()WHERE col IS NULLWHERE col IS NULL
совет

Всегда используйте IsNull() для поиска SQL NULL, независимо от API. Он корректно работает в высокоуровневых операциях и QueryBuilder.