Aller au contenu principal

33-4 Lien entre entité (modèle) et BD

Une base de données a été créée et notre application est en mesure de s'y connecter. La prochaine étape est de faire le lien entre une entité et une table de la base de données afin de profiter pleinement du concept d'ORM.

Par exemple, si vous avez une entité Projet dans l'application, vous devriez normalement avoir une table correspondante dans la base de données. TypeORM peut nous aider à décrire ce lien et même créer automatiquement la table.

Hériter de BaseEntity et ajout du décorateur @Entity()

Afin que l'entité puisse utiliser les fonctionnalités de TypeORM, on doit la faire hériter de BaseEntity et lui ajouter le décorateur @Entity().

src/projets/entities/projet.entity.ts
@Entity()
export class Projet extends BaseEntity {

Remarquez que cela a ajouté l'importation suivante, en provenance de TyeORM:

import { BaseEntity } from 'typeorm';

Utiliser le décorateur @Column()

TypeORM doit savoir quels attributs de l'entité sont associés à des colonnes de la table. Au fond, quels attributs sont considérés comme des colonnes. Le décorateur @Column() a cette responsabilité.

Ajoutez le décorateur @Column() sur la propriété nom:

src/projets/entities/projet.entity.ts
@ApiProperty({
description: 'Le nom du projet',
example: 'LAN Party',
})
@Column()
nom: string;

Préciser le type de la colonne et options

Un type de colonne sera associé par défaut en fonction du type TypeScript. Ceci étant dit, TypeScript est plutôt minimaliste dans les types, contrairement aux systèmes de base de données.

Par exemple, pour TypeScript, n'importe quelle valeur numérique est un number, alors que Postgres possède plusieurs variations: integer, decimal, etc.

Un autre cas de figure fréquent est la différence entre varchar et text, voire même être en mesure de préciser une contrainte comme varchar(255), par exemple.

Utilisons la description pour ce cas de figure. Il est possible de préciser le type et les contraintes:

src/projets/entities/projet.entity.ts
@Column({ type: 'varchar', length: 255 })
description: string;

Ou encore:

src/projets/entities/projet.entity.ts
@Column({ type: 'text' })
description: string;

Préciser qu'une colonne est nullable

Lorsqu'une colonne est nullable, puisqu'elle est optionnelle, on peut le définir explicitement. Par exemple, pour l'URL de l'image:

src/projets/entities/projet.entity.ts
@Column({ nullable: true })
imageUrl?: string;

Définir la clé primaire

Pour la propriété représentant la clé primaire (ex.: id), on peut ajouter un décorateur qui précise cette particularité:

src/projets/entities/projet.entity.ts
@PrimaryGeneratedColumn()
id: number;
info

@PrimaryGeneratedColumn fait référence à une colonne primaire dont l'identifiant sera autogénéré.

Timestamp de création et mise à jour

TypeORM peut gérer automatiquement l'assignation des timestamps de création et de modification, spécifiquement lorsqu'une entrée est créée dans la BD et lorsqu'une entrée est supprimée.

Pour cela, on utilise les décorateurs @CreateDateColumn() et @UpdateDateColumn().

src/projets/entities/projet.entity.ts
@ApiProperty()
@CreateDateColumn()
date_creation: string;

@ApiProperty()
@UpdateDateColumn()
date_modification: string;

Version complète de l'entité

La version complète de l'entité devrait ressembler à ceci:

src/projets/entities/projet.entity.ts
export class Projet extends BaseEntity {
@ApiProperty({
description: "L'identifiant du projet",
example: 1,
})
@PrimaryGeneratedColumn()
id: number;

@ApiProperty({
description: 'Le nom du projet',
example: 'LAN Party',
})
@Column()
nom: string;

@ApiProperty({
description: 'la description du projet',
example: "Tout ce qui à trait à l'organisation du LAN Party",
})
@Column({ type: 'text' })
description: string;

@ApiProperty({
description: "L'URL de l'image du projet",
example: 'https://i.imgur.com/Y5nZ4Qe.jpg',
})
@Column({ nullable: true })
imageUrl?: string;

@ApiProperty()
@CreateDateColumn()
date_creation: string;

@ApiProperty()
@UpdateDateColumn()
date_modification: string;
}

Enregistrer l'entité auprès de TypeORM

La dernière étape consiste à enregistrer l'entité auprès de TypeORM afin qu'il en connaisse l'existence.

Ajoutez la référence à l'entité Projet au tableau entities du module TypeORM.

src/app.module.ts
//...

TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.DATABASE_HOST,
port: +process.env.DATABASE_PORT!,
username: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
entities: [Projet],
synchronize: true,
logging: true,
}),

//...

Création automatique de la table

Si vous regardez la console, vous devriez voir que la requête suivante vient d'être exécutée!

CREATE TABLE "projet" ("id" SERIAL NOT NULL, "nom" character varying NOT NULL, "description" text NOT NULL, "imageUrl" character varying, "date_creation" TIMESTAMP NOT NULL DEFAULT now(), "date_modification" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_66b990dd579d8b7e5932661c389" PRIMARY KEY ("id"))

La table a été créée automatiquement!

Imgur

Préciser le nom de la table associée à l'entité

TypeORM a créé la table à partir du nom de l'entité, soit projet. Il est pratique courante en Postgres de nommer les tables au pluriel, donc projets.

  1. On peut spécifier le nom de la table associée à l'entité à l'aide de l'option name du décorateur @Entity().

    src/projets/entities/projet.entity.ts
    @Entity({ name: 'projets' })
    export class Projet extends BaseEntity {

    Ce qui aura comme effet de créer la table sous le nom projets

    CREATE TABLE "projets" ("id" SERIAL NOT NULL, "nom" character varying NOT NULL, "description" text NOT NULL, "imageUrl" character varying, "date_creation" TIMESTAMP NOT NULL DEFAULT now(), "date_modification" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_ad7c3b2fd59cc88ffa87968e9e1" PRIMARY KEY ("id"))

    Imgur

  2. Vous pouvez ensuite supprimer l'ancienne table projet Imgur

Level Up