Get a Quote Right Now

Edit Template

Using Validation

To use validation use class-validator. Example how to use class-validator with TypeORM: Validation:

Entity Subscriber

Marks a class as an event subscriber which can listen to specific entity events or any entity events. Events are firing using QueryBuilder and repository/manager methods. Example: You can implement any method from EntitySubscriberInterface. To listen to any entity you just omit listenTo method and use any: Make sure your subscribers property is set in your DataSourceOptions so TypeORM loads your subscriber. Event Object Excluding listenTo, all EntitySubscriberInterface methods are passed an event object that has the following base properties: Note: All database operations in the subscribed event listeners should be performed using the event object’s queryRunner or manager instance.

Entity Listener

Any of your entities can have methods with custom logic that listen to specific entity events. You must mark those methods with special decorators depending on what event you want to listen to. Note: Do not make any database calls within a listener, opt for subscribers instead. @AfterLoad You can define a method with any name in entity and mark it with @AfterLoad and TypeORM will call it each time the entity is loaded using QueryBuilder or repository/manager find methods. Example:  @BeforeInsert You can define a method with any name in entity and mark it with @BeforeInsert and TypeORM will call it before the entity is inserted using repository/manager save. Example: @AfterInsert You can define a method with any name in entity and mark it with @AfterInsert and TypeORM will call it after the entity is inserted using repository/manager save. Example: @BeforeUpdate You can define a method with any name in the entity and mark it with @BeforeUpdate and TypeORM will call it before an existing entity is updated using repository/manager save. Keep in mind, however, that this will occur only when information is changed in the model. If you run save without modifying anything from the model, @BeforeUpdate and @AfterUpdate will not run. Example: @AfterUpdate You can define a method with any name in the entity and mark it with @AfterUpdate and TypeORM will call it after an existing entity is updated using repository/manager save. Example: @BeforeRemove You can define a method with any name in the entity and mark it with @BeforeRemove and TypeORM will call it before a entity is removed using repository/manager remove. Example: @AfterRemove You can define a method with any name in the entity and mark it with @AfterRemove and TypeORM will call it after the entity is removed using repository/manager remove. Example:  @BeforeSoftRemove You can define a method with any name in the entity and mark it with @BeforeSoftRemove and TypeORM will call it before a entity is soft removed using repository/manager softRemove. Example: @AfterSoftRemove You can define a method with any name in the entity and mark it with @AfterSoftRemove and TypeORM will call it after the entity is soft removed using repository/manager softRemove. Example: @BeforeRecover You can define a method with any name in the entity and mark it with @BeforeRecover and TypeORM will call it before a entity is recovered using repository/manager recover. Example: @AfterRecover You can define a method with any name in the entity and mark it with @AfterRecover and TypeORM will call it after the entity is recovered using repository/manager recover. Example:

Creating and using transactions

Transactions are created using DataSource or EntityManager. Examples: or Everything you want to run in a transaction must be executed in a callback: The most important restriction when working in a transaction is to ALWAYS use the provided instance of entity manager – transactionalEntityManager in this example. DO NOT USE GLOBAL ENTITY MANAGER. All operations MUST be executed using the provided transactional entity manager. Using QueryRunner to create and control state of single database connection QueryRunner provides a single database connection. Transactions are organized using query runners. Single transactions can only be established on a single query runner. You can manually create a query runner instance and use it to manually control transaction state. Example: There are 3 methods to control transactions in QueryRunner:

Index in typeorm

Unique indices You can create a database index for a specific column by using @Index on a column you want to make an index. You can create indices for any columns of your entity. Example: You can also specify an index name: Unique indices To create an unique index you need to specify { unique: true } in the index options: Note: CockroachDB stores unique indices as UNIQUE constraints Indices with multiple columns To create an index with multiple columns you need to put @Index on the entity itself and specify all column property names which should be included in the index. Example:

Difference B/W CTE and Caching

Common Table Expression (CTE): A Common Table Expression (CTE) is a temporary result set that you can reference within a SELECT, INSERT, UPDATE, or DELETE statement in SQL. CTEs allow you to define subqueries that can be referenced multiple times within the main query. They improve code readability and maintainability by breaking down complex queries into more manageable parts. Pros of CTE: Cons of CTE: Caching in SQL and TypeORM: Caching involves storing frequently accessed data in memory so that future requests for the same data can be served faster. Caching can be implemented at both the database level and the application level (using an ORM like TypeORM). Pros of Caching: Cons of Caching: SQL-Level Caching vs. TypeORM Caching: SQL-level caching involves caching query results directly in the database, while TypeORM caching involves caching ORM query results in the application layer. In summary, CTEs are a query construct for breaking down complex queries, while caching improves performance by storing data in memory. Both have their benefits and considerations, and their usage depends on specific application requirements and performance needs. Common Table Expression (CTE) Example: Suppose you have an employee hierarchy stored in a table called employees with columns id, name, and manager_id. You want to retrieve all employees along with their managers in a single query using a CTE. WITH EmployeeHierarchy AS (SELECT id, name, manager_idFROM employeesWHERE manager_id IS NULL — Root managersUNION ALLSELECT e.id, e.name, e.manager_idFROM employees eINNER JOIN EmployeeHierarchy eh ON e.manager_id = eh.id)SELECT * FROM EmployeeHierarchy; In this example, the CTE EmployeeHierarchy is used to define a recursive query that retrieves employees and their managers. Caching Example (SQL-Level): Suppose you have an e-commerce application and want to cache the list of products for faster retrieval. — Assuming a caching mechanism is implemented in the databaseSELECT * FROM cached_products WHERE category = ‘electronics’; In this example, cached_products is a cached table where products of a specific category are stored for faster retrieval.

All-About-Migrations(create, run, revert)

Once you get into production you’ll need to synchronize model changes into the database. Typically, it is unsafe to use synchronize: true for schema synchronization on production once you get data in your database. Here is where migrations come to help. A migration is just a single file with sql queries to update a database schema and apply new changes to an existing database. Let’s say you already have a database and a post entity: And your entity worked in production for months without any changes. You have thousands of posts in your database. Now you need to make a new release and rename title to name. What would you do? You need to create a new migration with the following MYSQL query : Once you run this SQL query your database schema is ready to work with your new codebase. TypeORM provides a place where you can write such sql queries and run them when needed. This place is called “migrations”. Creating a new migration Pre-requisites: Installing CLI Before creating a new migration you need to setup your data source options properly: Here we setup two options: Once you setup connection options you can create a new migration using CLI: Here, PostRefactoring is the name of the migration – you can specify any name you want. After you run the command you can see a new file generated in the “migration” directory named {TIMESTAMP}-PostRefactoring.ts where {TIMESTAMP} is the current timestamp when the migration was generated. Now you can open the file and add your migration sql queries there. You should see the following content inside your migration: There are two methods you must fill with your migration code: up and down. up has to contain the code you need to perform the migration. down has to revert whatever up changed. down method is used to revert the last migration. Inside both up and down you have a QueryRunner object. All database operations are executed using this object. Learn more about query runner. Let’s see what the migration looks like with our Post changes: Running and reverting migrations Once you have a migration to run on production, you can run them using a CLI command: typeorm migration:create and typeorm migration:generate will create .ts files, unless you use the o flag (see more in Generating migrations). The migration:run and migration:revert commands only work on .js files. Thus the typescript files need to be compiled before running the commands. Alternatively you can use ts-node in conjunction with typeorm to run .ts migration files. Example with ts-node: Example with ts-node in ESM projects: This command will execute all pending migrations and run them in a sequence ordered by their timestamps. This means all sql queries written in the up methods of your created migrations will be executed. That’s all! Now you have your database schema up-to-date. If for some reason you want to revert the changes, you can run: This command will execute down in the latest executed migration. If you need to revert multiple migrations you must call this command multiple times. Faking Migrations and Rollbacks You can also fake run a migration using the –fake flag (-f for short). This will add the migration to the migrations table without running it. This is useful for migrations created after manual changes have already been made to the database or when migrations have been run externally (e.g. by another tool or application), and you still would like to keep a consistent migration history. This is also possible with rollbacks.

Caching queries in Typeorm

You can cache results selected by these QueryBuilder methods: getMany, getOne, getRawMany, getRawOne and getCount. You can also cache results selected by find* and count* methods of the Repository and EntityManager. To enable caching you need to explicitly enable it in data source options: When you enable cache for the first time, you must synchronize your database schema (using CLI, migrations or the synchronize data source option). Then in QueryBuilder you can enable query cache for any query: Equivalent Repository query: This will execute a query to fetch all admin users and cache the results. Next time you execute the same code, it will get all admin users from the cache. Default cache lifetime is equal to 1000 ms, e.g. 1 second. This means the cache will be invalid 1 second after the query builder code is called. In practice, this means that if users open the user page 150 times within 3 seconds, only three queries will be executed during this period. Any users inserted during the 1 second cache window won’t be returned to the user. You can change cache time manually via QueryBuilder: Or via Repository: Or globally in data source options:

Update using Query Builder

You can create UPDATE queries using QueryBuilder. Examples: This is the most efficient way in terms of performance to update entities in your database. Raw SQL support In some cases when you need to execute SQL queries you need to use function style value: This syntax doesn’t escape your values, you need to handle escape on your own.

Update values ON CONFLICT

If the values you are trying to insert conflict due to existing data the orUpdate function can be used to update specific values on the conflicted target.