TypeORM - Générateur de requêtes

Le générateur de requêtes est utilisé pour créer facilement des requêtes SQL complexes. Il est initialisé à partir de la méthode Connection et des objets QueryRunner.

Nous pouvons créer QueryBuilder de trois manières.

Connexion

Prenons un exemple simple d'utilisation de QueryBuilder à l'aide de la méthode de connexion.

import {getConnection} from "typeorm"; 

const user = await getConnection() .createQueryBuilder() 
.select("user") 
.from(User, "user") 
.where("user.id = :id", { id: 1 }) .getOne();

Gestionnaire d'entité

Créons un générateur de requêtes à l'aide du gestionnaire d'entités comme suit -

import {getManager} from "typeorm"; 

const user = await getManager() .createQueryBuilder(User, "user") .where("user.id = :id", { id: 1 })    .getOne();

Dépôt

Nous pouvons utiliser le référentiel pour créer un générateur de requêtes. Il est décrit ci-dessous,

import {getRepository} from "typeorm"; 

const user = await getRepository(User) .createQueryBuilder("user") .where("user.id = :id", { id: 1 }) .getOne();

Alias

Les alias sont identiques aux alias SQL. Nous créons un alias pour la table Student en utilisant QueryBuilder comme décrit ci-dessous -

import {getConnection} from "typeorm"; 

const user = await getConnection() .createQueryBuilder() 
.select("stud") 
.from(Student, "stud")

Cette requête équivaut à,

select * from students as stud

Paramètres

Parameterssont utilisés comme espaces réservés pour les valeurs dynamiques de la requête. Dans de nombreux cas, la requête pour trouver un objet entité différent sera la même à l'exception des valeurs. Par exemple, la requête pour trouver un élève différent est la même saufStudent IDLes données. Dans ce cas, nous pouvons utiliser le paramètre pourStudent ID puis modifiez le paramètre pour obtenir les différents objets étudiant.

Une autre utilisation importante du paramètre est d'empêcher l'injection SQL. C'est l'une des failles de sécurité les plus importantes de l'application Web moderne. En utilisant le paramètre dans la requête, nous pouvons survivre aux attaques par injection SQL.

Une autre utilisation importante du paramètre est d'empêcher l'injection SQL. C'est l'une des failles de sécurité les plus importantes de l'application Web moderne. En utilisant le paramètre dans la requête, nous pouvons survivre aux attaques par injection SQL.

Par exemple

"student.id = :id", { id: 1 }

Ici,

: id - nom du paramètre.

{id: 1} - valeur du paramètre

Ajouter une expression

Cette section explique comment utiliser les expressions.

where est utilisé pour filtrer les enregistrements si la condition est remplie.

createQueryBuilder("student") .where("student.id = :id", { id: 1 })

Cette requête équivaut à,

select * from students student where student.id=1;

Nous pouvons également utiliser des conditions AND, OR, NOT, IN à l'intérieur.

ayant

L'expression simple est définie ci-dessous -

createQueryBuilder("student") .having("student.id = :id", { id: 1 })

Cette requête équivaut à,

select * from students student having student.id=1;

commandé par

orderby est utilisé pour trier les enregistrements en fonction du champ.

createQueryBuilder("student") .orderBy("student.name")

Cette requête équivaut à,

select * from students student order by student.name;

par groupe

Il est utilisé pour regrouper les enregistrements en fonction de la colonne spécifiée.

createQueryBuilder("student") .groupBy("student.id")

Cette requête équivaut à,

select * from students student group by student.id;

limite

Il est utilisé pour limiter la sélection de lignes. Ci-dessous, un exemple montre comment utiliser la limite dans le générateur de requêtes,

createQueryBuilder("student") .limit(5)

Cette requête équivaut à,

select * from students student limit 5;

décalage

Offset est utilisé pour spécifier le nombre de lignes pour ignorer le résultat. Il est défini ci-dessous -

createQueryBuilder("student") .offset(5)

Cette requête équivaut à,

select * from students student offset 5;

joint

La clause join est utilisée pour combiner des lignes de deux ou plusieurs tables, en fonction d'une colonne associée. Considérez les deux entités -

Student.ts

import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm"; 
import {Project} from "./Project"; 

@Entity() 
export class User {
   
   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @OneToMany(type => Project, project => project.student) projects: project[]; 
}

Project.ts

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm"; 
import {Student} from "./Student"; 

@Entity() 
export class Project { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   title: string; 
   
   @ManyToOne(type => Student, student => student.projects) student: Student; 
}

Laissez-nous effectuer une simple jointure à gauche en utilisant la requête ci-dessous -

const student = await createQueryBuilder("student") .leftJoinAndSelect("student.projects", "project") 
.where("student.name = :name", { name: "Student1" }) 
.getOne();

Cette requête équivaut à,

SELECT student.*, project.* FROM students student 
   LEFT JOIN projects project ON project.student = student.id 
   WHERE student.name = 'Student1'

De même, nous pouvons également essayer la jointure interne.

Rejoindre sans sélection

Nous pouvons joindre des données sans utiliser select. Essayons cet exemple en utilisant la jointure intérieure comme suit -

const student = await createQueryBuilder("student") .innerJoin("student.projects", "project") 
   .where("student.name = :name", { name: "student1" }) 
   .getOne();

La requête ci-dessus équivaut à -

SELECT student.* FROM students student 
   INNER JOIN projects project ON project.student = student.id 
   WHERE student.name = 'Student1';

Pagination

Si vous avez plus de données dans votre application, vous avez besoin de fonctionnalités de pagination, de curseur de page ou de défilement.

Par exemple, si vous souhaitez afficher les cinq premiers projets d'étudiants dans votre application,

const students = await getRepository(Student) .createQueryBuilder("student") .leftJoinAndSelect("student.projects", "project") 
   .take(5) 
   .getMany();

sous-requêtes

Elle est appelée requête dans une autre requête ou requête imbriquée. Nous utilisons des sous-requêtes dans les expressions FROM, WHERE et JOIN.

Un exemple simple est montré ci-dessous -

const projects = await connection .createQueryBuilder() .select("project.id", "id")
.addSelect(subQuery => { 
   return subQuery 
      .select("student.name", "name") .from(Student, "student") 
      .limit(1); 
}, "name")
.from(Project, "project") .getMany();

Champ caché

Si l'un de vos champs de colonne est marqué comme {select: false}, cette colonne est considérée comme une colonne masquée. Considérez l'entité ci-dessous -

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm"; 

@Entity() 
export class Student {

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @Column({select: false}) 
   address: string; 
}

Ici,

address le champ est marqué comme hidden. On peut utiliseraddSelectméthode pour récupérer les informations de la colonne. Il est défini ci-dessous,

const student = await connection.getRepository(Student) .createQueryBuilder() .select("student.id", "student")    .addSelect("student.address") .getMany();

getSql ()

Cette méthode est utilisée pour obtenir la requête SQL générée par le générateur de requêtes. Il est défini ci-dessous -

const sql = createQueryBuilder("student") .where("student.name = :name", { name: "Student1" })  .orWhere("student.age = :age", { age: 14 }) 
.getSql();