Search⌘ K
AI Features

Introduction to TypeORM

Explore the foundational concepts of TypeORM, a TypeScript-based ORM for Node.js. Understand key decorators, entity relationships, and how to use the Repository API in a NestJS environment for efficient database management.

Overview

TypeORM has first-class support for TypeScript ORM in Node.js since it’s built purely on TypeScript. With TypeORM, like with every other ORM, we can easily work with any SQL database of our choice. TypeORM provides simple JavaScript methods and functions that can be easily understood.

Design pattern

One key aspect of TypeORM is its design pattern. This is another property that makes TypeORM unique among ORMs. The design pattern for TypeORM is the decorative design pattern. In the decorative design pattern, we can add behaviors dynamically to an object or class.

As the name implies, decorators are like icing on a cake. The cake (class/object) retains its taste (behavior), but the icing (decorators) can make it more palatable and even improve it by adding extra features and functionalities.

TypeScript 3.3.4
@Entity('care_team')
export class CareTeam {
@PrimaryGeneratedColumn()
id?: number;
@Column({ type: 'varchar', nullable: true })
hid: string;
@Column({
type: 'int',
nullable: true,
})
companyId?: number;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn() updatedAt: Date;
}

TypeORM decorators

The code snippet shows how a schema is defined using TypeORM. The most essential decorators include:

  • @Entity: This declares the class as a TypeORM entity.
  • @Column: This resolves each class property to an SQL column.
  • @PrimaryGeneratedColumn: This is used to define an auto-generated id column. Another alternative to this decorator is the @PrimaryColumn, which works in a similar way.

An entity must have at least one primary column.

Relational decorators

To establish a relationship between tables or entities, the following decorators are provided by TypeORM:

  • ManyToMany
  • ManyToOne
  • OneToMany
  • OneToOne

We can specify the datatype of the table columns by simply passing an object with a property of type as shown above. The supported datatypes are:

TypeScript 3.3.4
export type PrimaryGeneratedColumnType = "int" | "int2" | "int4" | "int8" | "integer" | "tinyint" | "smallint" | "mediumint" | "bigint" | "dec" | "decimal" | "smalldecimal" | "fixed" | "numeric" | "number";
export type SpatialColumnType = "geometry" | "geography" | "st_geometry" | "st_point";
export type WithPrecisionColumnType = "float" | "double" | "dec" | "decimal" | "smalldecimal" | "fixed" | "numeric" | "real" | "double precision" | "number" | "datetime" | "datetime2" | "datetimeoffset" | "time" | "time with time zone" | "time without time zone" | "timestamp" | "timestamp without time zone" | "timestamp with time zone" | "timestamp with local time zone";
export type WithLengthColumnType = "character varying" | "varying character" | "char varying" | "nvarchar" | "national varchar" | "character" | "native character" | "varchar" | "char" | "nchar" | "national char" | "varchar2" | "nvarchar2" | "alphanum" | "shorttext" | "raw" | "binary" | "varbinary" | "string";
export type WithWidthColumnType = "tinyint" | "smallint" | "mediumint" | "int" | "bigint";
export type SimpleColumnType = "simple-array" | "simple-json" | "simple-enum" | "int2" | "integer" | "int4" | "int8" | "int64" | "unsigned big int" | "float" | "float4" | "float8" | "smallmoney" | "money" | "boolean" | "bool" | "tinyblob" | "tinytext" | "mediumblob" | "mediumtext" | "blob" | "text" | "ntext" | "citext" | "hstore" | "longblob" | "longtext" | "alphanum" | "shorttext" | "bytes" | "bytea" | "long" | "raw" | "long raw" | "bfile" | "clob" | "nclob" | "image" | "timetz" | "timestamptz" | "timestamp with local time zone" | "smalldatetime" | "date" | "interval year to month" | "interval day to second" | "interval" | "year" | "seconddate" | "point" | "line" | "lseg" | "box" | "circle" | "path" | "polygon" | "geography" | "geometry" | "linestring" | "multipoint" | "multilinestring" | "multipolygon" | "geometrycollection" | "st_geometry" | "st_point" | "int4range" | "int8range" | "numrange" | "tsrange" | "tstzrange" | "daterange" | "enum" | "set" | "cidr" | "inet" | "macaddr" | "bit" | "bit varying" | "varbit" | "tsvector" | "tsquery" | "uuid" | "xml" | "json" | "jsonb" | "varbinary" | "hierarchyid" | "sql_variant" | "rowid" | "urowid" | "uniqueidentifier" | "rowversion" | "array" | "cube" | "ltree";

Outside the type property, TypeORM also provides other configurations for our table columns.

  • name: The column name in the database.
  • length: The column length in the database, which can be of type string or number.
  • width: The column display width. In MySQL, this is used on some column types.
  • nullable: In PostgreSQL, this enables us to save a column with null values as default if a value is not provided during the create operation. This configuration is of type boolean.
  • unique: Specifies if the column value is unique. This configuration is of type boolean.

Model layer

TypeORM provides the following APIs to interface with SQL databases:

  • EntityManagers
  • Repository

These APIs offer methods that carry out queries against the SQL database without us having to write the SQL queries directly.

Next we’ll focus on the Repository API and how it’s integrated with the NestJS library.

The Repository method

The Repository API follows the open/close and single responsibility principles in the SOLID design pattern. This means we develop repositories per entity with the same methods that can be extended or tuned but not modified.

The NestJS library is OOP based. We use the @InjectRepository decorator to inject a repository property into a service class or the classes responsible for CRUD and database operations from the @nestjs/typeorm module.

TypeScript 3.3.4
import { HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import Student from 'src/entities/student';
import { Repository } from 'typeorm';
@Injectable()
export class StudentsService {
constructor(
@InjectRepository(Student) private _studentRepo: Repository<Student>,
){}
async registerStudent(dt: IRegStudent): Promise<IResponse<Student>> {
let registerStudent: Student = await this._studentRepo.save({
name: dt.name,
sex: dt.sex,
class: dt.class,
});
}
}

TypeORM can be easily integrated with top Node.js libraries such as Express and NestJS.