Обработка значений null и undefined в условиях WHERE
Эта страница переведена PageTurner AI (бета). Не одобрена официально проектом. Нашли ошибку? Сообщить о проблеме →
В условиях 'WHERE' значения null и undefined не являются строго допустимыми в TypeORM.
Передача явного null запрещена TypeScript (при включённом strictNullChecks в tsconfig.json) на этапе компиляции. Однако поведение по умолчанию для значений null, обнаруженных во время выполнения, — их игнорирование. Аналогично значения undefined разрешены TypeScript и игнорируются при выполнении.
Такая обработка null и undefined иногда приводит к неожиданным результатам и требует осторожности. Особенно это критично при передаче значений из пользовательского ввода без должной валидации.
Например, вызов Repository.findOneBy({ id: undefined }) вернёт первую строку таблицы, а Repository.findBy({ userId: null }) не применит фильтрацию и вернёт все строки.
Поведение при обработке null и undefined можно настроить через опцию invalidWhereValuesBehavior в конфигурации источника данных. Это применяется ко всем операциям с условиями 'WHERE', включая методы поиска, построители запросов и репозитории.
Текущее поведение изменится в будущих версиях TypeORM.
Рекомендуем установить поведение для null и undefined в 'throw' для подготовки к этим изменениям.
Поведение по умолчанию
По умолчанию TypeORM пропускает значения null и undefined в условиях WHERE. Это означает, что если свойство в условии содержит null или undefined, оно будет проигнорировано:
// 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,
},
})
Корректный способ поиска значений null в условиях WHERE — использование оператора 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 connection 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 connection options to skip properties with undefined values.
Это относится только к явно установленным значениям undefined, а не к отсутствующим свойствам.
Совместное использование опций
Оба поведения можно настроить независимо для полного контроля:
const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
undefined: "throw",
},
})
Такая конфигурация:
-
Преобразует JavaScript
nullв SQLNULLв условиях WHERE -
Выбросит исключение при обнаружении значений
undefined -
Будет игнорировать свойства, отсутствующие в условии WHERE
Этот подход полезен, когда требуется:
-
Явно указывать поиск значений NULL в базе данных
-
Отлавливать потенциальные ошибки программирования, при которых значения undefined могут попасть в запросы
Применимость для всех операций
Конфигурация invalidWhereValuesBehavior действует для всех операций TypeORM с условиями WHERE, а не только для методов поиска в репозиториях:
Построители запросов
// 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.