Vai al contenuto principale

Gestione dei valori null e undefined nelle condizioni where

Traduzione Beta Non Ufficiale

Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →

Nelle condizioni 'WHERE', i valori null e undefined non sono strettamente validi in TypeORM.

TypeScript non consente di passare un valore null noto (quando è attivato strictNullChecks in tsconfig.json) durante la compilazione. Il comportamento predefinito prevede che i valori null e undefined rilevati a runtime generino un errore.

La gestione dei valori null e undefined può essere personalizzata tramite l'opzione di configurazione invalidWhereValuesBehavior nelle opzioni della sorgente dati. Questa si applica a operazioni di alto livello come le operazioni di ricerca, i metodi del repository e i metodi di EntityManager (update, delete, softDelete, restore).

avvertimento

Questa impostazione non influisce sui metodi .where(), .andWhere() o .orWhere() di QueryBuilder. QueryBuilder è un'API di basso livello dove i valori null/undefined passano così come sono. Usa l'operatore IsNull() o condizioni parametrizzate in QueryBuilder per gestire esplicitamente i null.

Comportamento Predefinito

Per impostazione predefinita, TypeORM genera un errore quando rileva valori null o undefined nelle condizioni where. Questo previene risultati inaspettati e aiuta a individuare potenziali bug precocemente:

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

Per cercare valori null nelle condizioni where, utilizza l'operatore IsNull (per dettagli vedi Opzioni di ricerca):

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

Configurazione

È possibile personalizzare la gestione dei valori null e undefined tramite l'opzione invalidWhereValuesBehavior nella configurazione della sorgente dati:

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

Opzioni per Null

Il comportamento per null può essere impostato su tre valori:

'ignore'

I valori JavaScript null nelle condizioni WHERE vengono ignorati e la proprietà è esclusa:

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'

I valori JavaScript null vengono convertiti in condizioni 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' (predefinito)

I valori JavaScript null causano il lancio di un 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.

Opzioni per Undefined

Il comportamento per undefined può essere impostato su due valori:

'ignore'

I valori JavaScript undefined nelle condizioni WHERE vengono ignorati e la proprietà è esclusa:

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' (predefinito)

I valori JavaScript undefined causano il lancio di un 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.

Nota: si applica solo a valori undefined esplicitamente impostati, non a proprietà omesse.

Utilizzo Combinato

Puoi configurare entrambi i comportamenti indipendentemente per un controllo completo:

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

Questa configurazione:

  1. Trasforma i valori JavaScript null in SQL NULL

  2. Genera un errore per valori undefined

  3. Ignora comunque le proprietà non fornite nella clausola WHERE

Questa combinazione è utile quando vuoi:

  • Essere esplicito nella ricerca di valori NULL nel database

  • Rilevare potenziali errori di programmazione dove valori undefined potrebbero essere introdotti nelle query

Operazioni supportate

La configurazione invalidWhereValuesBehavior si applica alle operazioni di alto livello di TypeORM, non al metodo diretto .where() di QueryBuilder:

Operazioni di ricerca

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

Metodi di Repository e 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 con 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()

Non interessato: QueryBuilder .where()

I metodi .where(), .andWhere() e .orWhere() di QueryBuilder sono API di basso livello e non sono influenzati da questa impostazione. I valori null e undefined passano così come sono:

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

Comportamento di null e undefined in QueryBuilder .where()

Poiché QueryBuilder è un'API di basso livello, i valori null e undefined non vengono validati né trasformati. Comprenderne il comportamento è fondamentale per evitare risultati inaspettati.

null nel metodo QueryBuilder .where()

Quando null viene passato come valore in un .where() in stile oggetto, genera un controllo di uguaglianza SQL contro NULL:

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

In SQL, column = NULL è sempre falso — nulla è uguale a NULL. Questa query restituirà zero risultati, quasi certamente non ciò che intendevi. Per cercare valori NULL, usa l'operatore IsNull():

import { IsNull } from "typeorm"

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

Oppure usa una condizione testuale:

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

undefined nel metodo QueryBuilder .where()

Quando undefined viene passato come valore, si applica lo stesso comportamento — genera WHERE column = NULL, che è sempre falso:

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

Tabella riepilogativa

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
consiglio

Usa sempre IsNull() quando vuoi cercare valori SQL NULL, indipendentemente dall'API utilizzata. Funziona correttamente sia in contesti di alto livello che in QueryBuilder.