I have a custom repository class like this with NestJS/Typeorm:
import { Repository, EntityRepository, getConnection } from 'typeorm';
import { RefreshToken } from './refresh-token.entity';
import { User } from './user.entity';
import { InternalServerErrorException } from '@nestjs/common';
@EntityRepository(RefreshToken)
export class RefreshTokenRepository extends Repository<RefreshToken> {
async refreshToken({ token, user }: RefreshToken): Promise<RefreshToken> {
const connection = getConnection();
const queryRunner = connection.createQueryRunner();
// establish real database connection using our new query runner
await queryRunner.connect();
// lets now open a new transaction:
await queryRunner.startTransaction();
try {
// execute some operations on this transaction:
await queryRunner.manager.delete(RefreshToken, { token });
const refreshToken = await queryRunner.manager.save(
this.buildToken(user),
);
// commit transaction now:
await queryRunner.commitTransaction();
return refreshToken;
} catch (err) {
// since we have errors lets rollback changes we made
await queryRunner.rollbackTransaction();
} finally {
// you need to release query runner which is manually created:
await queryRunner.release();
}
}
}
Is there a different way to make/build a transaction than the one I did in refreshToken()
method please? Because getting a connection feels broken and not appropriate with the way NestJS works.
Thanks.
You can use the official integration (package @nestjs/typeorm
) in order for your code not to care about getting a connection to the database (official documentation).
With TypeOrmModule
(@nestjs/typeorm
), you can create (and import) a dynamic module responsible for establishing a connection to the database.
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'root',
database: 'test',
entities: [],
synchronize: true,
}),
],
})
export class AppModule {}
Then you don't need to care about the connection in the code of your repositories.
If you already created a connection using "raw" TypeORM (let's say, when your app start), then the Repository
already knows how to use it. You can proceed to your request directly, doing something like this:
try {
const refreshToken = await this.manager.transaction(async entityManager => {
await entityManager.delete(RefreshToken, { token });
return entityManager.save(RefreshToken, this.buildToken(user));
});
// commit done: use refreshToken here
} catch (error) {
// rollback done: handle error here
}
You cannot start the transaction directly from the repository but you can access (public API) to its manager, which can start a transaction. It provides an entity manager that *must be used for all operations of the transaction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With