-> ACID 특성을 보장하기 위해 회복, 병행 제어 기능이 필요하다.
await getConnection().transaction(async transactionalEntityManager => {
await transactionalEntityManager.save(users);
// ...
});
await getManager().transaction(async transactionalEntityManager => {});
@Transaction
@Transaction({ isolation: "SERIALIZABLE" })
@TransactionManager
@Transaction()
save(@TransactionManager() manager: EntityManager, user: User) {
return manager.save(user);
}
@TransactionRepository
@Transaction()
save(user: User, @TransactionRepository(User) userRepository: Repository<User>) {
return userRepository.save(user);
}
-주요 메소드: startTransaction
, commitTransaction
, rollbackTransaction
, release
import {getConnection} from "typeorm";
// get a connection and create a new query runner
const connection = getConnection();
const queryRunner = connection.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();
}
Isolation Level 이란?
- 동시에 여러 트랜잭션이 처리될 때, 트랜잭션 간의 고립된 정도
- 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것
(자세한 내용은 Locking과 각 레벨의 상세 설명 찾아보기)
Isolation Level 설정하기
- 첫 번째 매개변수에 격리 수준을 전달한다.
- 종류:
READ UNCOMMITTED
,READ COMMITTED
,REPEATABLE READ
,SERIALIZABLE
await getManager().transaction("SERIALIZABLE", manager => {});
QueryRunner
클래스 사용을 권장한다.@Injectable()
export class UsersService {
constructor(private connection: Connection) {}
}
async createMany(users: User[]) {
// 1. queryRunner 사용
const queryRunner = this.connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
await queryRunner.manager.save(users[0]);
await queryRunner.commitTransaction();
} catch (err) {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
}
// 2. callbackk 스타일 사용
await this.connection.transaction(async manager => {
await manager.save(users[0]);
});
}
This is a great idea, it will definitely be shared widely, thanks for sharing it with us quordle