TypeORM Documentation

website·Indexed 31 days ago

https://notprisma.devinda.me/

An Object-Relational Mapper (ORM) that can be used with TypeScript and JavaScript. The documentation covers the EntityManager and Repository APIs, QueryBuilder for select and update operations, migrations, and database schema definition using decorators like @Entity and @Column. It provides detailed guides on relations (one-to-one, many-to-one, many-to-many), tree entities, transactions, and integration with Express.

Tokens
48.9K
Snippets
280
Records
307
Agent score
50%

What's inside TypeORM

  1. Introduction to TypeORM QueryBuilder

    The QueryBuilder allows developers to build SQL queries using a fluent API, executing them to receive automatically transformed entities. It abstracts raw SQL while providing a convenient syntax for complex queries.
    const firstUser = await connection
        .getRepository(User)
        .createQueryBuilder("user")
        .where("user.id = :id", { id: 1 })
        .getOne();
  2. Understand the purpose of QueryRunner in TypeORM

    While TypeORM's Connection manages a connection pool, QueryRunner provides a single, isolated database connection. Use QueryRunner when you need a dedicated connection to ensure queries execute on the same session or to manually control database transactions.
  3. Understand TypeORM Connection and Connection Pools

    In TypeORM, the Connection class does not represent a single physical database connection, but rather a connection pool. The pool is established when the connect method is called (which happens automatically when using createConnection). To interact with a single, isolated database connection, use QueryRunner. Typically, a connection should be created once during application bootstrap and only closed (via close) when the application is shutting down.
  4. Run TypeORM in Cordova, PhoneGap, or Ionic apps

    TypeORM supports Cordova, PhoneGap, and Ionic apps using the cordova-sqlite-storage plugin. Note that for Ionic apps, a custom webpack configuration file is required.
  5. Use embedded entities in EntitySchema

    You can embed one schema into another using the embeddeds property. This allows you to group related columns into a separate schema and include them in a parent entity with an optional prefix.
    import { EntitySchema } from "typeorm";
    
    export const NameEntitySchema = new EntitySchema<Name çı}({
        name: "name",
        columns: {
            first: { type: "varchar" },
            last: { type: "varchar" }
        },
    });
    
    export const UserEntitySchema = new EntitySchema<User>({
        name: "user",
        columns: {
            id: { primary: true, generated: "uuid", type: "uuid" },
            isActive: { type: "boolean" }
        },
        embeddeds: {
            name: {
                schema: NameEntitySchema,
                prefix: "name_",
            },
        }
    });
  6. Access TypeORM repositories in external files

    When extracting route logic into separate files, use getRepository() or getConnection().getRepository() to access the entity repository without passing the connection object manually.
    import { getRepository } from "typeorm";
    import { User } from "./entity/User";
    
    export function UsersListAction(req: Request, res: Response) {
        return getRepository(User).find();
    }
  7. Implement Single Table Inheritance

    Single Table Inheritance is a pattern where multiple classes with different properties are stored in a single database table. This is achieved by using the @TableInheritance decorator on the base entity to specify a discriminator column (e.g., type) and the @ChildEntity decorator on the extending classes.
    @Entity()
    @TableInheritance({ column: { type: "varchar", name: "type" } })
    export class Content {
        @PrimaryGeneratedColumn()
        id: number;
    
        @Column()
        title: string;
    
        @Column()
        description: string;
    }
    
    @ChildEntity()
    export class Photo extends Content {
        @Column()
        size: string;
    }
    
    @ChildEntity()
    export class Question extends Content {
        @Column()
        answersCount: number;
    }
    
    @ChildEntity()
    export class Post extends Content {
        @Column()
        viewCount: number;
    }
  8. Implement pagination with skip and take

    For methods returning multiple entities (find, findAndCount, findByIds), use skip (offset) and take (limit) to paginate results.

    Caveat for MSSQL: When using take or limit with SQL Server, you must also provide an order option to avoid the error: 'Invalid usage of the option NEXT in the FETCH statement.'

    userRepository.find({
        order: { columnName: "ASC" },
        skip: 0,
        take: 10,
    });
  9. Create many-to-many relations with custom properties

    If a many-to-many relationship requires additional columns (e.g., an order or timestamp column), you cannot use @JoinTable. Instead, you must create a separate 'join entity' that contains two @ManyToOne relations pointing to the target entities, along with the custom columns. The original entities then use @OneToMany to point to this join entity.
    // Join Entity
    @Entity()
    export class PostToCategory {
        @PrimaryGeneratedColumn() public postToCategoryId!: number;
        @Column() public order!: number;
    
        @ManyToOne(() => Post, post => post.postToCategories)
        public post!: Post;
    
        @ManyToOne(() => Category, category => category.postToCategories)
        public category!: Category;
    }
    
    // Post Entity
    @Entity()
    export class Post {
        @OneToMany(() => PostToCategory, postToCategory => postToCategory.post)
        public postToCategories!: PostToCategory[];
    }
    
    // Category Entity
    @Entity()
    export class Category {
        @OneToMany(() => PostToCategory, postToCategory => postToCategory.category)
        public postToCategories!: PostToCategory[];
    }
  10. Create a TypeORM connection using a configuration file

    TypeORM can automatically load connection options from a configuration file located in the project root (near package.json). To use this, call createConnection() without passing any arguments. Supported file formats include .json, .js, .ts, .env, .yml, and .xml.
    import {createConnection} from "typeorm";
    
    // createConnection method will automatically read connection options
    // from your ormconfig file or environment variables
    const connection = await createConnection();
  11. Implement a custom NamingStrategy in the connection configuration

    To use a custom naming strategy, instantiate your NamingStrategy class and pass it to the namingStrategy property within the connection options. If using an ormconfig file, you can retrieve the existing options via getConnectionOptions(), merge the custom strategy using Object.assign(), and then initialize the connection with createConnection().
    import {createConnection, getConnectionOptions} from "typeorm";
    import {MyNamingStrategy} from "./logger/MyNamingStrategy";
    
    // getConnectionOptions reads options from the ormconfig file
    getConnectionOptions().then(connectionOptions => {
        return createConnection(Object.assign(connectionOptions, {
            namingStrategy: new MyNamingStrategy()
        }))
    });