Soft Delete는 논리 삭제라고도 부른다.
실제 DB에서의 작업은 update와 같다. 삭제 여부를 저장하는 컬럼을 업데이트하는 것이다.
Typeorm으로는 @DeletedDateColumn() 데코레이터를 써서 soft delete를 구현할 수 있다.
import {
Column,
CreateDateColumn,
DeleteDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column()
username: string;
@Column()
password: string;
@CreateDateColumn({ type: 'timestamp' })
create_at: Date;
@UpdateDateColumn({ type: 'timestamp' })
update_at: Date;
// null이 디폴트로 저장된다.
@DeleteDateColumn()
deletedAt: Date | null;
}
import { Repository } from 'typeorm';
@Injectable()
export class UserService {
constructor(
@InjectRepository(User) private userRepository: Repository<User>,
) {}
async softDeleteUser(id: number) {
const existingUser: User = await this.userRepository.findOne({
where: { id },
relations: ['boards'],
});
if (!existingUser) {
throw new NotFoundException('id와 일치하는 유저가 없습니다.');
}
try {
await this.userRepository.softDelete(id); 📌
return { message: '회원탈퇴를 완료했습니다.' };
} catch (error) {
throw new HttpException('서버 에러', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
softDelete메소드가 정상 작동하면 deleted_at 컬럼에 삭제를 한 날짜가 저장된다.
soft-delete된 행도 조회하고 싶다면 withDeleted:true 옵션을 사용한다.
const users = await userRepository.find({
withDeleted: true,
});
const userWithDeleted = await userRepository.findOne(id, {
withDeleted: true,
});
const softDeletedUsers = await userRepository
.createQueryBuilder('user')
.where('user.deletedAt IS NOT NULL')
.getMany();
// 일단, soft-delete된 행을 조회합니다.
const softDeletedUser = await userRepository.findOne(id, {
withDeleted: true,
});
if (softDeletedUser) {
// deletedAt 속성을 null로 설정하여 복원합니다.
softDeletedUser.deletedAt = null;
// 변경된 속성을 저장합니다.
await userRepository.save(softDeletedUser);
}
update user set deleted_at = null
where id in (select id from user where deleted_at is not null)
이런식으로 하면 이런 에러를 만난다.
Error: ER_UPDATE_TABLE_USED: You can't specify target table 'user' for update in FROM clause
MySQL에서는 한 번에 하나의 테이블만 업데이트하거나 다른 테이블을 참조할 수 있기 때문에 이런 에러가 발생한다.
UPDATE user
JOIN (SELECT id FROM user
WHERE deleted_at IS NOT NULL) AS deleted_user
ON user.id = deleted_user.id
SET user.deleted_at = NULL;