TypeORM is an ORM framework that runs on NodeJS, browsers, Cordova, PhoneGap, Ionic, React Native, Expo, and Electron. Works with TypeScript and JavaScript (ES5, ES6, ES7). Its goal is to always support the latest JavaScript features and provide additional features to help you develop any application that uses a database — whether it’s a small application with just a few tables or a large enterprise application with multiple databases.

Unlike all other existing JavaScript ORM frameworks, TypeORM supports Active Record and Data Mapper patterns, which means you write high-quality, loosely coupled, extensible, and maintainable applications in the most efficient way possible.

TypeORM references many other good ORM implementations, such as Hibernate, Doctrine, and Entity Framework.

Some features of TypeORM:

  • Support for Active Record and Data Mapper (optional)
  • Entities and column
  • Database feature column type
  • Entity management
  • Repositories and custom repositories
  • Clean the object relationship model
  • Association (relation)
  • Greed and delay
  • Unidirectional, bidirectional, and self-referential relationships
  • Multiple inheritance patterns are supported
  • cascade
  • The index
  • The transaction
  • Migration and automatic migration
  • The connection pool
  • copy
  • Use multiple database connections
  • Use multiple database types
  • Query across databases and schemas
  • Elegant syntax, flexible and powerful QueryBuilder
  • Left join and inside join
  • Accurate paging connection queries
  • The query cache
  • Raw result stream
  • The log
  • Listeners and Subscribers (hooks)
  • Supports the closure table pattern
  • Declare schemas in models or separate configuration files
  • Connection configuration in JSON/XML/yML/env format
  • Support MySQL/MariaDB/Postgres/SQLite/Microsoft SQL Server/Oracle/sqL.js
  • Support MongoDB NoSQL database
  • Work on NodeJS/browser/Ionic/Cordova/React Native/Expo/Electron
  • Supports TypeScript and JavaScript
  • The result is high-performance, flexible, clear, and maintainable code
  • Follow all possible best practices
  • Command line tool

There’s more…

Using TypeORM your model looks like this:

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

@Entity(a)export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

    @Column()
    age: number;

}
Copy the code

Your domain logic looks like this:

const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.age = 25;
await repository.save(user);

const allUsers = await repository.find();
const firstUser = await repository.findOne(1);
const timber = await repository.findOne({ firstName: "Timber", lastName: "Saw" });

await repository.remove(timber);
Copy the code

Alternatively, if you prefer to use the “ActiveRecord” implementation, you can use it:

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

@Entity(a)export class User extends BaseEntity {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

    @Column()
    age: number;

}
Copy the code

Your domain logic looks like this:

const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.age = 25;
await user.save();

const allUsers = await User.find();
const firstUser = await User.findOne(1);
const timber = await User.findOne({ firstName: "Timber", lastName: "Saw" });

await timber.remove();
Copy the code

Please note that

This document may not be up to date. You can go to the official website to see the latest English documents. Your contributions are most welcome.

The installation

  1. Install TypeORM:

    npm install typeorm --save

  2. Dependency module reflect-metadata needs to be installed:

    npm install reflect-metadata --save

    Globally referenced in the application:

    • Like at the entrance to app.tsrequire("reflect-metadata")
  3. You may need to install the Node type:

    npm install @types/node --save

  4. Install the database driver:

    • MySQL and MariaDB

      npm install mysql --save

    • PostgreSQL

      npm install pg --save

    • SQLite

      npm install sqlite3 --save

    • Microsoft SQL Server

      npm install mssql --save

    • sql.js

      npm install sql.js --save

    • Oracle (experimental)

      npm install oracledb --save

    You can install any of the above depending on your database.

    For details about how to use the Oracle driver, see installation instructions: Address.

TypeScript configuration

Make sure your TypeScript compiler is older than 2.3 and enable the following Settings in tsconfig.json:

"emitDecoratorMetadata": true,
"experimentalDecorators": true,
Copy the code

You also need to enable ES6 under lib in the build options or install ES6-shim from @typings

Quick start

The fastest way to get started with TypeORM is to generate an initial project using its CLI commands. Quick start is only available when using TypeORM in NodeJS applications. If you’re using another platform, see the step-by-step guide.

First install TypeORM globally:

npm install typeorm -g
Copy the code

Then go to the directory for the new project and run the command:

typeorm init --name MyProject --database mysql
Copy the code

Name is the name of the project, and database is the database you will use. The database can be one of the following values: mysql, Mariadb, Postgres, SQLite, MSSQL, Oracle, mongodb, Cordova, React-Native, or Expo.

This command will generate a new project in the MyProject directory containing the following files:

MyProject ├ ─ ─ SRC / / put your TypeScript code │ ├ ─ ─ the entity / / put entity model (database) directory │ │ └ ─ ─ the User. The ts/case/entity │ ├ ─ ─ migration / / migration file directory │ └ ─ ─ index. Ts / / application entry ├ ─ ─ the gitignore / / standard git ignore file ├ ─ ─ ormconfig. Json / / ORM and data connection configuration ├ ─ ─ package. The json / / the node module relies on ├ ─ ─ └─ garbage, └─ tsconfig.json // TypeScriptCopy the code

You can also execute TypeOrm Init in an existing Node project directory, but be careful – it may overwrite some files you already have.

The next step is to install project dependencies

cd MyProject
npm install
Copy the code

During installation, modify the ormconfig.json file to include your own database connection configuration options:

{
   "type": "mysql"."host": "localhost"."port": 3306."username": "test"."password": "test"."database": "test"."synchronize": true."logging": false."entities": [
      "src/entity/**/*.ts"]."migrations": [
      "src/migration/**/*.ts"]."subscribers": [
      "src/subscriber/**/*.ts"]}Copy the code

In general, most of the time you only need to configure the host, username, password, database, or port options.

With configuration and module installation complete, the application is ready to run:

npm start
Copy the code

That’s it, your application should run successfully and insert a new user into the database. You can go ahead with the project, integrate the other modules you need, and create more entities.

You can install Express by running typeorm init –name MyProject –database mysql –express to generate a more advanced project.

Step by step guide

What are your expectations for ORM? First, you expect it to create database tables for you and find/insert/update/delete your data without having to write a lot of hard-to-maintain SQL queries. This guide will show you how to set up TypeORM from scratch and make it behave as you expect ORM to behave.

Create the model

Working with a database starts by creating tables. How do I tell TypeORM to create a database table? The answer is – through the model. The models in your application are the tables in your database.

For example, you have a Photo model:

export class Photo {
    id: number;
    name: string;
    description: string;
    filename: string;
    views: number;
}
Copy the code

You want to store photos in your database. To store something in a database, you first need a database table and create the database table from the model. Not all models, just those you define as entities.

Create the entity

Entities are models that you decorate with @entity. A database table will be created for these models. With TypeORM you will use entities everywhere. You can use them to load/insert/update/delete and perform other operations.

Let’s turn the Photo model into an entity:

import {Entity} from "typeorm";

@Entity(a)export class Photo {
    id: number;
    name: string;
    description: string;
    filename: string;
    views: number;
    isPublished: boolean;
}
Copy the code

Now, we will create a database table for the Photo entity that we can use anywhere in the application. We have created a database table, but no column representation does not exist. Let’s create some columns in the database table.

Add database table columns

To add database columns, simply decorate the attributes of the generated entity with @column.

import {Entity, Column} from "typeorm";

@Entity(a)export class Photo {

    @Column()
    id: number;

    @Column()
    name: string;

    @Column()
    description: string;

    @Column()
    filename: string;

    @Column()
    views: number;

    @Column()
    isPublished: boolean;
}
Copy the code

The ID, name, Description, filename, views and isPublished columns will now be added to the photo table. The column types in the database are inferred from the attribute types you use, for example: Number will be converted to INTEGER, String to vARCHar, Boolean to bool, and so on. But you can specify the Column type as any type your database supports by implicitly passing it in the @column decorator.

We’ve generated a database table with columns, but there’s only one thing left. Each database table must have a column with a primary key.

Create a primary key column

Every table must have at least one primary key column. It’s a requirement that you can’t avoid. To make a column the primary key, you need to use the @primaryColumn modifier.

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

@Entity(a)export class Photo {

    @PrimaryColumn()
    id: number;

    @Column()
    name: string;

    @Column()
    description: string;

    @Column()
    filename: string;

    @Column()
    views: number;

    @Column()
    isPublished: boolean;
}
Copy the code

Create an automatically generated column

Now, suppose you want the ID column to be generated automatically (this is called auto-incrementing/sequential/sequential/generating uniquely identified columns). To do this, you need to change the @primaryColumn decorator to the @primaryGeneratedColumn decorator:

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

@Entity(a)export class Photo {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @Column()
    description: string;

    @Column()
    filename: string;

    @Column()
    views: number;

    @Column()
    isPublished: boolean;
}
Copy the code

Column data type

Next, let’s fix the data type. By default, strings are mapped to a VARCHAR (255) type (depending on the database type). The number is mapped to an INTEGER type (depending on the database type). We don’t want all columns to be finite Varchars or integers. Let’s set the correct data type:

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

@Entity(a)export class Photo {

    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        length: 100
    })
    name: string;

    @Column("text")
    description: string;

    @Column()
    filename: string;

    @Column("double")
    views: number;

    @Column()
    isPublished: boolean;
}
Copy the code

Column types depend on the types supported by the database. You can set any column type supported by the database. More information about the supported column types can be found here.

Creating a database connection

Now that we have the entity, let’s create a new file named index.ts (or app.ts, whatever you call it) and configure the database connection:

import "reflect-metadata";
import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";

createConnection({
    type: "mysql",
    host: "localhost",
    port: 3306,
    username: "root",
    password: "admin",
    database: "test",
    entities: [
        Photo
    ],
    synchronize: true,
    logging: false
}).then(connection= > {
    // Here you can write entity manipulation code
}).catch(error= > console.log(error));
Copy the code

In this example, mysql is used. You can also select other databases by simply changing the type of database in the driver option, such as: Mysql, Mariadb, Postgres, SQLite, MSSQL, Oracle, Cordova, React-native, Expo, or mongodb can also change host, port, username, or port. Password and database Settings.

Add the Photo entity to the list of entities for the data connection. All entities that need to be used under the connection must be added to the list.

The Synchronize option ensures that your entity is in sync with your database when your application starts.

References all entities under the directory

We may then create more entities and add them to the configuration. It is possible to write the entity directory directly, so that all entities in this directory can be used in the current connection:

import {createConnection} from "typeorm";

createConnection({
    driver: {
        type: "mysql",
        host: "localhost",
        port: 3306,
        username: "root",
        password: "admin",
        database: "test"
    },
    entities: [
        __dirname + "/entity/*.js"
    ],
    synchronize: true,
}).then(connection= > {
    // here you can start to work with your entities
}).catch(error= > console.log(error));
Copy the code

Start the application

Now you can start app.ts and see that the database is automatically initialized and the Photo table is created.

+-------------+--------------+----------------------------+
|                         photo                           |
+-------------+--------------+----------------------------+
| id          | int(11)      | PRIMARY KEY AUTO_INCREMENT |
| name        | varchar(500) |                            |
| description | text         |                            |
| filename    | varchar(255) |                            |
| views       | int(11)      |                            |
| isPublished | boolean      |                            |
+-------------+--------------+----------------------------+
Copy the code

Add and insert photo

Now create a new photo and store it in the database:

import {createConnection} from "typeorm";

createConnection(/ *... * /).then(connection= > {

    let photo = new Photo();
    photo.name = "Me and Bears";
    photo.description = "I am near polar bears";
    photo.filename = "photo-with-bears.jpg";
    photo.views = 1;
    photo.isPublished = true;

    connection.manager
            .save(photo)
            .then(photo= > {
                console.log("Photo has been saved");
            });

}).catch(error= > console.log(error));
Copy the code

Use async/await syntax

Now use TypeScript async/await syntax to do the same:

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";

createConnection(/ *... * /).then(async connection => {

    let photo = new Photo();
    photo.name = "Me and Bears";
    photo.description = "I am near polar bears";
    photo.filename = "photo-with-bears.jpg";
    photo.views = 1;
    photo.isPublished = true;

    await connection.manager.save(photo);
    console.log("Photo has been saved");

}).catch(error= > console.log(error));
Copy the code

Use the EntityManager

We just created a new photo and put it in the database. You use EntityManager to manipulate entities, so now you use EntityManager to get photo out of the database.

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";

createConnection(/ *... * /).then(async connection => {

    / *... * /
    let savedPhotos = await connection.manager.find(Photo);
    console.log("All photos from the db: ", savedPhotos);

}).catch(error= > console.log(error));
Copy the code

What savedPhotos is going to fetch from the database is an array of Photo objects

Use Repositories

Now refactor the code to use Repository instead of EntityManage. Each entity has its own repository, and you can do anything with that entity. If you need to do a lot of work on entities, Repositories would be more convenient than EntityManager.

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";

createConnection(/ *... * /).then(async connection => {

    let photo = new Photo();
    photo.name = "Me and Bears";
    photo.description = "I am near polar bears";
    photo.filename = "photo-with-bears.jpg";
    photo.views = 1;
    photo.isPublished = true;

    let photoRepository = connection.getRepository(Photo);

    await photoRepository.save(photo);
    console.log("Photo has been saved");

    let savedPhotos = await photoRepository.find();
    console.log("All photos from the db: ", savedPhotos);

}).catch(error= > console.log(error));
Copy the code

Take photos from the database

Now try fetching some data using Repository:

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";

createConnection(/ *... * /).then(async connection => {

    / *... * /
    let allPhotos = await photoRepository.find();
    console.log("All photos from the db: ", allPhotos);

    let firstPhoto = await photoRepository.findOne(1);
    console.log("First photo from the db: ", firstPhoto);

    let meAndBearsPhoto = await photoRepository.findOne({ name: "Me and Bears" });
    console.log("Me and Bears photo from the db: ", meAndBearsPhoto);

    let allViewedPhotos = await photoRepository.find({ views: 1 });
    console.log("All viewed photos: ", allViewedPhotos);

    let allPublishedPhotos = await photoRepository.find({ isPublished: true });
    console.log("All published photos: ", allPublishedPhotos);

    let [allPhotos, photosCount] = await photoRepository.findAndCount();
    console.log("All photos: ", allPhotos);
    console.log("Photos count: ", photosCount);

}).catch(error= > console.log(error));
Copy the code

Update the photo

Now let’s take a photo out of the database, modify it and update it to the database.

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";

createConnection(/ *... * /).then(async connection => {

    / *... * /
    let photoToUpdate = await photoRepository.findOne(1);
    photoToUpdate.name = "Me, my friends and polar bears";
    await photoRepository.save(photoToUpdate);

}).catch(error= > console.log(error));
Copy the code

This photo with id = 1 is successfully updated in the database.

Delete the photo

Again, delete our photo from the database:

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";

createConnection(/ *... * /).then(async connection => {

    / *... * /
    let photoToRemove = await photoRepository.findOne(1);
    await photoRepository.remove(photoToRemove);

}).catch(error= > console.log(error));
Copy the code

That photo with id = 1 is removed from the database.

One-to-one relationship

To create a one-to-one relationship with another class. Create PhotoMetadata. Ts to store the meta information of photo.

import {Entity, Column, PrimaryGeneratedColumn, OneToOne, JoinColumn} from "typeorm";
import {Photo} from "./Photo";

@Entity(a)export class PhotoMetadata {

    @PrimaryGeneratedColumn()
    id: number;

    @Column("int")
    height: number;

    @Column("int")
    width: number;

    @Column()
    orientation: string;

    @Column()
    compressed: boolean;

    @Column()
    comment: string;

    @OneToOne(type= > Photo)
    @JoinColumn()
    photo: Photo;
}
Copy the code

Here we use a new decorator, @oneToone, which can be used to create a one-to-one relationship between two entities. Type => Photo indicates the name of the entity class we want to connect to, which cannot be used directly because of TypeScript language support. You could also use () => Photo, but type => Photo is more readable. The Type variable does not contain anything by itself.

We also use the @JoinColumn decorator, which specifies the owner of a one-to-one relationship. Relationships can be unidirectional or bidirectional, but only one party is the owner, adding this decorator to indicate that the relationship serves the table.

Now run the app and create a new table with a foreign key attached to photo:

+ -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + | photo `. Should be PhotoMetadata ` | + -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + | | id int (11) | PRIMARY KEY AUTO_INCREMENT | | height | int(11) | | | width | int(11) | | | comment | varchar(255) | | | compressed | boolean | | | orientation | varchar(255) | | | photoId | int(11) | FOREIGN KEY | +-------------+--------------+----------------------------+Copy the code

Have a one to one relationship

Now let’s create a photo, a photo meta-information, and concatenate them.

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";
import {PhotoMetadata} from "./entity/PhotoMetadata";

createConnection(/ *... * /).then(async connection => {

    // Create a photo
    let photo = new Photo();
    photo.name = "Me and Bears";
    photo.description = "I am near polar bears";
    photo.filename = "photo-with-bears.jpg"
    photo.isPublished = true;

    // Create a photo meta-information
    let  metadata = new PhotoMetadata();
    metadata.height = 640;
    metadata.width = 480;
    metadata.compressed = true;
    metadata.comment = "cybershoot";
    metadata.orientation = "portait";
    metadata.photo = photo; // Connect the two

    // Get Entity Repositories
    let photoRepository = connection.getRepository(Photo);
    let metadataRepository = connection.getRepository(PhotoMetadata);

    // Let's save photo to the database
    await photoRepository.save(photo);

    // When photo is saved, store the meta information of photo
    await metadataRepository.save(metadata);

    / / done
    console.log("metadata is saved, and relation between metadata and photo is created in the database too");

}).catch(error= > console.log(error));
Copy the code

Two-way relationship

Relationships can be one-way or two-way. At present, the relationship between PhotoMetadata and Photo is one-way. The owner of the relationship is PhotoMetadata. Photo does not know PhotoMetadata, so it will be troublesome to get the data of PhotoMetadata from Photo. Now to change this, change one-way to two-way:

import {Entity, Column, PrimaryGeneratedColumn, OneToOne, JoinColumn} from "typeorm";
import {Photo} from "./Photo";

@Entity(a)export class PhotoMetadata {

    / *... The other columns * /

    @OneToOne(type= > Photo, photo= > photo.metadata)
    @JoinColumn()
    photo: Photo;
}
Copy the code
import {Entity, Column, PrimaryGeneratedColumn, OneToOne} from "typeorm";
import {PhotoMetadata} from "./PhotoMetadata";

@Entity(a)export class Photo {

    / *... The other columns * /

    @OneToOne(type= > PhotoMetadata, photoMetadata= > photoMetadata.photo)
    metadata: PhotoMetadata;
}
Copy the code

Photo => photo. Metadata is the name of the field used to specify the inverse relationship. Photo. It is possible to use @onetoone (‘metadata’) for the same purpose, but this is not friendly for future code refactoring.

As stated above, @JoinColumn can only be used on one side of the relationship to make that side the owner of the relationship. The owner of the relationship is represented in the database as having a foreign key column.

Retrieves data from a relational object

Now let’s use a query to retrieve photo and its meta information. There are two ways to do this, one is to use FindOptions, the other is to use QueryBuilder. Try FindOptions first. Using the repository. find method by specifying the FindOptions interface as an argument can do very complex queries.

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";
import {PhotoMetadata} from "./entity/PhotoMetadata";

createConnection(/ *... * /).then(async connection => {

    / *... * /
    let photoRepository = connection.getRepository(Photo);
    let photos = await photoRepository.find({ relations: ["metadata"]}); }).catch(error= > console.log(error));
Copy the code

The photos returned are an array of photos retrieved from the database, each containing its meta information.

Alias is a mandatory option for FindOptions. This is the alias you define yourself in select and then use in where, Order by, Group by, JOIN, and other expressions.

We also use innerJoinAndSelect, which represents an inline query of the photo. Metadata data. In “photo. Metadata “, “photo” is an alias, and “metadata” is the property name of the object you want to query. “Metadata “: a new alias for the inline returned data.

Let’s try the second approach: QueryBuilder to achieve the same goal. Use QueryBuilder to elegantly complete complex queries:

import {createConnection} from "typeorm";
import {Photo} from "./entity/Photo";
import {PhotoMetadata} from "./entity/PhotoMetadata";

createConnection(/ *... * /).then(async connection => {

    / *... * /
    let photos = await connection
            .getRepository(Photo)
            .createQueryBuilder("photo")
            .innerJoinAndSelect("photo.metadata"."metadata")
            .getMany();


}).catch(error= > console.log(error));
Copy the code

Use the Cascade option to automatically save the associated objects

Above to save the relationship objects need to save one by one, slightly troublesome. If we want to save one of the relational objects as well as the other, we can use the Cascade option to do so. Change the @oneToOne decoration slightly:

export class Photo {
    / / /... The other columns

    @OneToOne(type= > PhotoMetadata, metadata= > metadata.photo, {
        cascade: true,
    })
    metadata: PhotoMetadata;
}
Copy the code

If you use Cascade, you don’t need to store photo first and then metadata as above. Now let’s just store the photo object, and metadata will be stored automatically because of Cascade.

createConnection(options).then(async connection => {

    // Create a photo object
    let photo = new Photo();
    photo.name = "Me and Bears";
    photo.description = "I am near polar bears";
    photo.filename = "photo-with-bears.jpg"
    photo.isPublished = true;

    // Create photo Metadata object
    let metadata = new PhotoMetadata();
    metadata.height = 640;
    metadata.width = 480;
    metadata.compressed = true;
    metadata.comment = "cybershoot";
    metadata.orientation = "portait";
    
    photo.metadata = metadata; // connect

    / / get the repository
    let photoRepository = connection.getRepository(Photo);

    // 存photo
    await photoRepository.save(photo);
    // Photo metadata is automatically saved
    console.log("Photo is saved, photo metadata is saved too.")

}).catch(error= > console.log(error));
Copy the code

Many-to-one/one-to-many relationships

Next the many-to-one/one-to-many relationship is displayed. Suppose a photo has one author, and each author can have many photos. Create the Author entity first:

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

@Entity(a)export class Author {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @OneToMany(type= > Photo, photo= > photo.author) // Note: The author attribute for Photo will be created below
    photos: Photo[];
}
Copy the code

Author contains an inverted relationship, OneToMany is always inverted, and is always paired with ManyToOne.

Now let’s add the relational owner to Photo.

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

@Entity(a)export class Photo {

    / *... The other columns * /

    @ManyToOne(type= > Author, author= > author.photos)
    author: Author;
}
Copy the code

In a ManyToOne/OneToMany relationship, the owner side is always ManyToOne. The field with the foreign key, the owner of the relationship (ManyToOne), holds the ID of another object. In the database, the type of the author id is the type of the author ID

Executing the above code automatically creates the author table as follows:

+-------------+--------------+----------------------------+
|                          author                         |
+-------------+--------------+----------------------------+
| id          | int(11)      | PRIMARY KEY AUTO_INCREMENT |
| name        | varchar(255) |                            |
+-------------+--------------+----------------------------+
Copy the code

Since the photo table already exists, instead of adding to the photo table, modify it – add a new foreign key column author:

+-------------+--------------+----------------------------+ | photo | +-------------+--------------+----------------------------+ | id | int(11) | PRIMARY KEY AUTO_INCREMENT | | name | varchar(255) | | | description | varchar(255) | | | filename | varchar(255) | | | isPublished | boolean | | | authorId |  int(11) | FOREIGN KEY | +-------------+--------------+----------------------------+Copy the code

Many-to-many relationships

Suppose a photo can exist in more than one album, and an album can contain more than one photo. Start by creating an Album class

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

@Entity(a)export class Album {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @ManyToMany(type= > Photo, photo= > photo.albums)
    @JoinTable()
    photos: Photo[];
}
Copy the code

@JoinTable The owner of the many-to-many relationship must be specified.

Then add a reverse relationship to the Photo entity:

export class Photo {
    / / /... The other columns

    @ManyToMany(type= > Album, album= > album.photos)
    albums: Album[];
}
Copy the code

Executing the above code automatically creates a join table called album_photoS_photo_Albums:

+-------------+--------------+----------------------------+
|                album_photos_photo_albums                |
+-------------+--------------+----------------------------+
| album_id    | int(11)      | PRIMARY KEY FOREIGN KEY    |
| photo_id    | int(11)      | PRIMARY KEY FOREIGN KEY    |
+-------------+--------------+----------------------------+
Copy the code

Remember to add the Album entity to ConnectionOptions:

const options: ConnectionOptions = {
    / /... Other configuration
    entities: [Photo, PhotoMetadata, Author, Album]
};
Copy the code

Now insert Albums and photos into the database

let connection = await createConnection(options);

// Create a few albums
let album1 = new Album();
album1.name = "Bears";
await connection.manager.save(album1);

let album2 = new Album();
album2.name = "Me";
await connection.manager.save(album2);

// Create a few photos
let photo = new Photo();
photo.name = "Me and Bears";
photo.description = "I am near polar bears";
photo.filename = "photo-with-bears.jpg";
photo.albums = [album1, album2];
await connection.manager.save(photo);

// Now our photos have been saved and added to the album
// Let's start loading them:
const loadedPhoto = await connection
    .getRepository(Photo)
    .findOne(1, { relations: ["albums"]});Copy the code

LoadedPhoto will look like this:

{
    id: 1,
    name: "Me and Bears",
    description: "I am near polar bears",
    filename: "photo-with-bears.jpg",
    albums: [{
        id: 1,
        name: "Bears"
    }, {
        id: 2,
        name: "Me"}}]Copy the code

Use the criteriabuilder

You can use QueryBuilder to build a very complex query, for example:

let photos = await connection
    .getRepository(Photo)
    .createQueryBuilder("photo") // first argument is an alias. Alias is what you are selecting - photos. You must specify it.
    .innerJoinAndSelect("photo.metadata"."metadata")
    .leftJoinAndSelect("photo.albums"."album")
    .where("photo.isPublished = true")
    .andWhere("(photo.name = :photoName OR photo.name = :bearName)")
    .orderBy("photo.id"."DESC")
    .skip(5)
    .take(10)
    .setParameters({ photoName: "My", bearName: "Mishka" })
    .getMany();
Copy the code

This query will look for published columns whose name is “My” or “Mishka”. The results will start at number 5 (determined by paging offset) and only get 10 results (determined by number of pages per page). The results are sorted in reverse order of id. Photo’s Albums are left joined, and Photo’s metadata is inline joined.

You will use QueryBuilder a lot in your applications. Learn more about QueryBuilder here.

The sample

See how these examples are used in the sample

These warehouses you can clone to help you get started:

  • Example how to use TypeORM with TypeScript
  • Example how to use TypeORM with JavaScript
  • Example how to use TypeORM with JavaScript and Babel
  • Example how to use TypeORM with TypeScript and SystemJS in Browser
  • Example how to use Express and TypeORM
  • Example how to use Koa and TypeORM
  • Example how to use TypeORM with MongoDB
  • Example how to use TypeORM in a Cordova/PhoneGap app
  • Example how to use TypeORM with an Ionic app
  • Example how to use TypeORM with React Native
  • Example how to use TypeORM with Electron using JavaScript
  • Example how to use TypeORM with Electron using TypeScript

extension

These extensions simplify the use of TypeORM and integrate it with other modules:

  • TypeORM + GraphQL framework
  • TypeORM integration with TypeDI
  • TypeORM integration with routing-controllers
  • Models generation from existing database – typeorm-model-generator

Reprinted from: Click to view documentation sources

Leave a message

Welcome to the Mock Server front-end Mock interface and data scheme implemented using TypeORM and NestJS