Transaction Management
Handle database transactions for data consistency.
TypeORM Transactionsโ
Using QueryRunnerโ
async transferFunds(fromId: string, toId: string, amount: number) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
await queryRunner.manager.decrement(Account, { id: fromId }, 'balance', amount);
await queryRunner.manager.increment(Account, { id: toId }, 'balance', amount);
await queryRunner.commitTransaction();
} catch (err) {
await queryRunner.rollbackTransaction();
throw err;
} finally {
await queryRunner.release();
}
}
Using @Transaction Decoratorโ
@Transaction()
async createInvoiceWithItems(
@TransactionManager() manager: EntityManager,
dto: CreateInvoiceDTO
) {
const invoice = await manager.save(Invoice, dto);
const items = dto.items.map(item => ({
...item,
invoiceId: invoice.id,
}));
await manager.save(InvoiceItem, items);
return invoice;
}
Using EntityManagerโ
await this.dataSource.transaction(async (manager) => {
const employee = await manager.save(Employee, employeeData);
const user = await manager.save(User, {
...userData,
employeeId: employee.id,
});
return { employee, user };
});
Transaction Isolation Levelsโ
| Level | Dirty Read | Non-Repeatable | Phantom |
|---|---|---|---|
| READ UNCOMMITTED | โ | โ | โ |
| READ COMMITTED | โ | โ | โ |
| REPEATABLE READ | โ | โ | โ |
| SERIALIZABLE | โ | โ | โ |
await this.dataSource.transaction("SERIALIZABLE", async (manager) => {
// Strictest isolation
});
Best Practicesโ
- Keep transactions short
- Avoid long-running queries inside transactions
- Handle deadlocks with retry logic
- Use the lowest isolation level that ensures correctness
Related Pagesโ
- Database Schema โ schema
- Query Builder โ complex queries
- Connection Pooling โ pool management