I have a setup for my NestJS application in which I am using typeorm with a PostgreSQL database. In the setup, I am using repository mode to query the database. Now I want to use database transactions with my queries, but I am not able to use transactions because I am using one transaction with multiple queries from different repositories, and a transaction uses an entity manager, which has to be used to query the database in order to access the same transaction for all the queries in the scope.
Entity One
@Injectable()
export class EntityOneService extends BaseService<EntityOne> {
repository: Repository<EntityOne>;
constructor(private connection: Connection) {
super();
this.repository = this.connection.getRepository(EntityOne);
}
}
Entity Two
import { Injectable } from '@nestjs/common';
import { Connection, Repository } from 'typeorm';
import { EntityTwo } from '../entities/lesson.entity';
import { BaseService } from './baseService/base-service.service';
@Injectable()
export class EntityTwoService extends BaseService<EntityTwo> {
repository: Repository<EntityTwo>;
constructor(private connection: Connection) {
super();
this.repository = this.connection.getRepository(EntityTwo);
}
}
This is how to initialize the repository from a database table. Now I want to query the database using transaction in repository mode.
const entityOne = await this.entityOneService.find()
const entityTwo = await this.entityTwoService.find()
I want to query both with the same transaction. I have user sequelize
before typeorm, and in sequelize there is a method named transaction
which can used as follows.
this.sequelize.transaction(async transaction => {
const entityOne = await this.entityOneService.findAll({transaction})
const entityTwo = await this.entityTwoService.findAll({transaction})
})
I want to do something like that in typeorm, if possible how can I implement it?
CodePudding user response:
Transactions
- Creating and using transactions
- Using
QueryRunner
to create and control state of single database connection
Creating and using transactions
Transactions are created using DataSource
or EntityManager
.
Examples:
await myDataSource.transaction(async (transactionalEntityManager) => {
// execute queries using transactionalEntityManager
});
or
await myDataSource.manager.transaction(async (transactionalEntityManager) => {
// execute queries using transactionalEntityManager
});
Everything you want to run in a transaction must be executed in a callback:
await myDataSource.manager.transaction(async (transactionalEntityManager) => {
await transactionalEntityManager.save(users);
await transactionalEntityManager.save(photos);
// ...
});
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:
// create a new query runner
const queryRunner = dataSource.createQueryRunner();
// establish real database connection using our new query runner
await queryRunner.connect();
// now we can execute any queries on a query runner, for example:
await queryRunner.query("SELECT * FROM users");
// we can also access entity manager that works with connection created by a query runner:
const users = await queryRunner.manager.find(User);
// lets now open a new transaction:
await queryRunner.startTransaction();
try {
// execute some operations on this transaction:
await queryRunner.manager.save(user1);
await queryRunner.manager.save(user2);
await queryRunner.manager.save(photos);
// commit transaction now:
await queryRunner.commitTransaction();
} catch (err) {
// since we have errors let's rollback changes we made
await queryRunner.rollbackTransaction();
} finally {
// you need to release query runner which is manually created:
await queryRunner.release();
}
There are 3 methods to control transactions in QueryRunner
:
startTransaction
- starts a new transaction inside the query runner instance.commitTransaction
- commits all changes made using the query runner instance.rollbackTransaction
- rolls all changes made using the query runner instance back.
Source: https://typeorm.io/transactions
CodePudding user response:
https://stackoverflow.com/a/70140732 I think this is an example for a solution with multiple repositories.