데이터베이스 트랜젝션은 데이터베이스 관리 시스템에서의 작업 단위를 뜻하는 단어입니다. 그리고 데이터베이스의 모든 변경 사항을 뜻합니다.
그리고 TypeORM transaction을 처리하기 위해 여러 방법이 있는데 그 중 좋은게 QueryRunner
클래스를 사용하는 것입니다.
왜냐하면 이 클래스가 트렌젝션을 모두 관리할 수 있게 해주기 때문입니다.
먼저, Connection Object를 사용할 수 있게 해야한다.
@Injectable()
export class UsersService {
constructor(private connection: Connection) {}
}
이 때, Connection은 typeorm 패키지 안에 있습니다.
그리고 이제 본격적으로 트랜젝션을 만들 것인데,
async createMany(users: User[]) {
const queryRunner = this.connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
await queryRunner.manager.save(users[0]);
await queryRunner.manager.save(users[1]);
await queryRunner.commitTransaction();
} catch (err) {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
}
}
공식 문서에서 보여주는 코드입니다. queryRunner를 이해하기 위해서 위 사이트를 참고했습니다.
이라는 뜻 같다.
코드를 보면 queryRunner를 시작한 후, 값들을 저장한 후 커밋시킵니다.
하지만 에러가 발생한다면 롤백시키고 마지막엔 배포를 시키는 것입니다.
그리고 트랜젝션을 제어하기 위해 @Transaction()
이나 @TransactionManager()
을 비추한다고 적혀있습니다.
구독자가 아니라 청취자? 정도로 이해하면 될 것 같다.
왜냐면 js에서 EventListener가 있듯이 여기엔 @EventSubscribers
가 있기에 그렇게 생각해봤다.. ㅎㅎ
그렇다고 EventSubscribers
가 모든 이벤트를 청취하는 것은 아니고
특정 엔티티 이벤트를 청취하는 것이니 헷갈리면 안될 것 같다.
어쨌든 코드를 보며 이해해보자.
import {
Connection,
EntitySubscriberInterface,
EventSubscriber,
InsertEvent,
} from 'typeorm';
import { User } from './user.entity';
@EventSubscriber()
export class UserSubscriber implements EntitySubscriberInterface<User> {
constructor(connection: Connection) {
connection.subscribers.push(this);
}
listenTo() {
return User;
}
beforeInsert(event: InsertEvent<User>) {
console.log(`BEFORE USER INSERTED: `, event.entity);
}
}
생성자에서 push를 하는 것을 봤을 때 subscribers는 배열일 수 있다는 생각이 들었고 beforeInsert
를 통해서 console을 한번 찍을 수 있고 listenTo
는 청취된 것들을 출력시키는 것이 아닐까라는 생각을 했다.