LikeCount와 같은 테이블의 number 칼럼에 +1 혹은 -1을 할 일이 생기는 경우, +1을 하는 API를 새로 구성하는 것 보다 Like 테이블에 row가 추가될 때마다 SubScriber에서 트랜잭션을 열고, +1을 추가하는 것이 프론트의 api 호출 빈도를 줄일 수 있다는 점에서 장점이 있다고 생각하였다.
+1의 경우, TypeORM afterInsert( )를 사용하여 insertEvent가 해당 테이블에서 발생시 number +=1을 하는 방식으로 작성하여, 정상적으로 likeCount 칼럼의 값에 +1이 되는 것을 확인하였는데, -1의 경우, 테이블에서 해당 정보가 삭제되더라도 removeEvent가 row가 삭제된 것을 체크하지않아 -=1이 되지않는 문제가 발생하였다.
원인
Delete 메소드를 활용하는 REST api는 Service단에서 repository.delete({id})를 사용하여 id 값을 통해 해당 row를 삭제하는 경우가 많았다. 관련 TypeORM Issue를 살펴보면 repository.delete()를 사용하지 말고, repository.remove()를 사용하면 removeEvent가 작동한다고 되어있다.
해당 removeEvent가 작동해야되는 Delete 메소드 API의 Service 부분을 repository.delete({id})에서 repository.remove(repository)의 방식으로 변경하였다.
.delete()를 사용할 때는 아래와 같이 테이블에서 검색하지않고, 바로 id값만을 통해 삭제하였다.
deleteLikeById(id: number) {
returnthis.repository.delete({ id });
}
.remove의 경우, 아래와 같이 테이블에서 id값을 통해 find를 해와서 불러온 해당 엔티티 자체를 삭제하는 방식으로 하였다.
asyncdeleteLike(id: number) {
const like = awaitthis.repository.findOne({ id });
this.repository.remove(like);
}
해결된 이유
평소라면 "해결했다~"하고 끝내겠지만, .remove와 .delete 어떻게 보면 '삭제'라는 동일한 기능을 하는 함수를 굳이? typeorm에서 두 가지로 나눠서 구현해놓은 이유와 .remove와 .delete의 차이점, 왜 removeEvent는 delete() 사용시 작동하지않는지 모르겠어서 이에 대해 알아보았다. TypeORM 깃헙의 repository API 문서를 확인해보면 아래와 같이 설명되어있다.
repository.remove( )
한 트랜잭션안에 주어진 Entity나 Entitiy Array를 삭제한다. 삭제된 Entity 혹은 Entities를 리턴합니다.
repository.delete( )
주어진 id, ids 또는 조건으로 Entitiy를 삭제합니다.
위의 두 설명만 봐도 왜 removeEvent의 Entiity가 undefined였는지 이해가 되었다. .remove의 경우, 삭제하고 나서 해당 삭제된 Entity를 리턴하지만, .delete의 경우, 리턴하는 값 없이 삭제해버린다.
SubScriber afterRemove( )에서 removeEvent의 Entity가 notFound인 이유
LikeCount와 같은 테이블의 number 칼럼에 +1 혹은 -1을 할 일이 생기는 경우, +1을 하는 API를 새로 구성하는 것 보다 Like 테이블에 row가 추가될 때마다 SubScriber에서 트랜잭션을 열고, +1을 추가하는 것이 프론트의 api 호출 빈도를 줄일 수 있다는 점에서 장점이 있다고 생각하였다.
+1의 경우, TypeORM afterInsert( )를 사용하여 insertEvent가 해당 테이블에서 발생시 number +=1을 하는 방식으로 작성하여, 정상적으로 likeCount 칼럼의 값에 +1이 되는 것을 확인하였는데, -1의 경우, 테이블에서 해당 정보가 삭제되더라도 removeEvent가 row가 삭제된 것을 체크하지않아 -=1이 되지않는 문제가 발생하였다.
원인
Delete 메소드를 활용하는 REST api는 Service단에서 repository.delete({id})를 사용하여 id 값을 통해 해당 row를 삭제하는 경우가 많았다. 관련 TypeORM Issue를 살펴보면 repository.delete()를 사용하지 말고, repository.remove()를 사용하면 removeEvent가 작동한다고 되어있다.
Undefined entity on RemoveEvent · Issue #6876 · typeorm/typeorm
Issue type: [x] bug report [ ] feature request [ ] documentation issue Database system/driver: [ ] cordova [ ] mongodb [ ] mssql [x] mysql / mariadb [ ] oracle [ ] postgres [ ] cockroachdb [ ] sqli...
github.com
해결방법
해당 removeEvent가 작동해야되는 Delete 메소드 API의 Service 부분을 repository.delete({id})에서 repository.remove(repository)의 방식으로 변경하였다.
.delete()를 사용할 때는 아래와 같이 테이블에서 검색하지않고, 바로 id값만을 통해 삭제하였다.
deleteLikeById(id: number) { return this.repository.delete({ id }); }
.remove의 경우, 아래와 같이 테이블에서 id값을 통해 find를 해와서 불러온 해당 엔티티 자체를 삭제하는 방식으로 하였다.
async deleteLike(id: number) { const like = await this.repository.findOne({ id }); this.repository.remove(like); }
해결된 이유
평소라면 "해결했다~"하고 끝내겠지만, .remove와 .delete 어떻게 보면 '삭제'라는 동일한 기능을 하는 함수를 굳이? typeorm에서 두 가지로 나눠서 구현해놓은 이유와 .remove와 .delete의 차이점, 왜 removeEvent는 delete() 사용시 작동하지않는지 모르겠어서 이에 대해 알아보았다. TypeORM 깃헙의 repository API 문서를 확인해보면 아래와 같이 설명되어있다.
repository.remove( )
한 트랜잭션안에 주어진 Entity나 Entitiy Array를 삭제한다. 삭제된 Entity 혹은 Entities를 리턴합니다.
repository.delete( )
주어진 id, ids 또는 조건으로 Entitiy를 삭제합니다.
위의 두 설명만 봐도 왜 removeEvent의 Entiity가 undefined였는지 이해가 되었다. .remove의 경우, 삭제하고 나서 해당 삭제된 Entity를 리턴하지만, .delete의 경우, 리턴하는 값 없이 삭제해버린다.
결론은 "공식 깃헙에서 문서를 잘 읽어보자" 였다.참고) https://github.com/typeorm/typeorm/blob/master/docs/repository-api.md
'개발 > TypeORM' 카테고리의 다른 글