๐ซง @SQLDelete
JPA์์ ๊ธฐ๋ณธ์ ์ธ ์ญ์ ๋ Hard Delete๋ก ๋์ด ์๋ค.
์ด ์ญ์ ๋ฐฉ์์ @SQLDelete๋ฅผ ํตํด ์ฟผ๋ฆฌ๋ฅผ ์์ฑํด๋๋ฉด, delete๊ฐ ํธ์ถ๋ ๋ ๋ฐ์ดํฐ๋ฅผ ์ค์ ๋ก ์ญ์ ํ์ง ์๊ณ ๋ฏธ๋ฆฌ ์ ์ํด๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋๋ก ๋ฐฉ์ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค.
Hard Delete
๋ฌผ๋ฆฌ ์ญ์ ๋ผ๊ณ ๋ ํ๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ Delete Query๋ฅผ ๋ ๋ ค ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ค์ ๋ก ์ญ์ ํ๋ค.
Soft Delete
๋ ผ๋ฆฌ ์ญ์ ๋ผ๊ณ ๋ ํ๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ Update Query๋ฅผ ๋ ๋ ค ํด๋น ๋ฐ์ดํฐ๊ฐ ์ญ์ ๋ ๊ฒ์ ํ๋์ ์ปฌ๋ผ์ ์ด์ฉํ์ฌ ๊ตฌ๋ถํ๋ค.
@SQLDelete๋ ๋ ผ๋ฆฌ ์ญ์ ๋ฅผ ์ํ ๊ธฐ๋ฅ์ธ ๊ฒ์ด๋ค.
๐ซง ๋ฌธ์ ๋ฐ๊ฒฌ
ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ค๊ฐ ๋ฐ๊ฒฌํ๊ฒ ๋ ๋ฌธ์ ..
@Test
@DisplayName("ํ์์ ๋
ผ๋ฆฌ ์ญ์ ํ๋ค")
void succeed_to_soft_delete_user() {
// given
User foundUser = userRepository.findById(user.getId()).get();
// when
userRepository.delete(foundUser);
// then
System.out.println(foundUser.getIsDeleted());
}

์์ ํ ์คํธ๋ฅผ ์คํํด ๋ณด๋ฉด UPDATE ์ฟผ๋ฆฌ๋ ์คํ๋์ง ์๊ณ INSERT ์ฟผ๋ฆฌ๋ง ์คํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ํ isDeleted๊ฐ ์ฌ์ ํ false์ธ๋ฐ, ์ด๋ SQLDelete๋ ์์์ฑ ์ปจํ ์คํธ์์ ๊ด๋ฆฌ๋๋ค๊ฐ ํธ๋์ญ์ ์ด ๋๋๊ณ ์ค์ DB์ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ผ๋ ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ๋๋ฌธ์ด๋ค. (์ง์ฐ ์ฐ๊ธฐ, flush๊ฐ ๋ฐ์ํด์ผ ๋จ)
๊ทผ๋ฐ!!! ๋ด๊ฐ ํ์ฐธ ํค๋งธ๋ ๊ฒ์ SELECT ์ฟผ๋ฆฌ๋ ์คํ์ด ์๋๋ค๋ ๊ฑฐ์๋ค.
@Test
@DisplayName("ํ์์ ๋
ผ๋ฆฌ ์ญ์ ํ๋ค")
void succeed_to_soft_delete_user() {
// given
User foundUser = userRepository.findById(user.getId()).get();
// when
userRepository.delete(foundUser);
User deletedUser = userRepository.findById(foundUser.getId()).orElse(null);
// then
System.out.println("isDeleted After delete: " + deletedUser);
}

๋ถ๋ช findById๋ก foundUser๋ ์์ํ๊ฐ ๋์ด์์ ํ ๋ฐ userRepository.findById()์ ๊ฒฐ๊ณผ๊ฐ null์ด ๋์ค๋ ๊ฒ์ด ๋์ ํ ์ดํด๊ฐ ๊ฐ์ง์์๋ค.
findById ์กฐํ๊ฐ ์๋๋๊น flush ํด ์์์ฑ ์ปจํ ์คํธ์ ๋ณ๊ฒฝ ๋ด์ฉ์ DB์ ๋ฐ์ํ ํ ์ด๊ธฐํ ํด๋ณด์๋ค.
๊ทธ ํ ๋ค์ findById ๋ฉ์๋๋ฅผ ํตํด deletedUser๋ฅผ ์์์ฑ ์ปจํ ์คํธ์ ์ฌ๋ ค ๋ณด์๋ค.
@Test
@DisplayName("ํ์์ ๋
ผ๋ฆฌ ์ญ์ ํ๋ค")
void succeed_to_soft_delete_user() {
// given
User foundUser = userRepository.findById(user.getId()).get();
// when
userRepository.delete(foundUser);
em.flush();
em.clear();
User deletedUser = userRepository.findById(user.getId()).get();
// then
assertThat(deletedUser).isNotNull();
System.out.println("๋์ผ์ฑ ๊ฒ์ฆ: " + (foundUser == deletedUser));
System.out.println("foundUser is_deleted: " + foundUser.getIsDeleted());
System.out.println("deletedUser is_deleted: " + deletedUser.getIsDeleted());
}

๊ทธ๋ฐ๋ฐ ๊ฐ์๊ธฐ UPDATE ๋ฌธ์ด ์คํ๋๋๋ฐ, foundUser๋ deletedUser์๋ ๋ฌ๋ฆฌ deleted_at ํ๋๊ฐ ๊ฐฑ์ ๋์ง ์์ ์ด ๋์ ๋์ผ์ฑ์ด ๊นจ์ง๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ด๋ ๊ณง foundUser๋ ์ด๋ ์๊ฐ๋ถํฐ ๋น์์ํ๋ ์ํ์์ ์๋ฏธํ๋ค.
๐ซง ์ ๋น์์ํ ๋๋๋ฐ?!?
์์ํ๋ foundUser๋ฅผ softDete ์ฒ๋ฆฌํ๊ณ , findById()๋ฅผ ํตํด User ์ํฐํฐ๋ฅผ ๊ฐ์ ธ์ค๋ฉด ์ ๋ฐํ๊ฐ์ด null์ด์์๊น?
๋๋ ๋จ์ํ deleted_at ํ๋๊ฐ ์์ ๋๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง SQLDelete๋ฅผ ํตํด ์ํ๋๋ UPDATE ๋ฌธ์ ๋จ์ํ ์์ ์ด ์๋ ์ญ์ ์ ๋ชฉ์ ์ ๊ฐ๋ ์์ ์ด๋ค. ๋ฐ๋ผ์ soft delete๋ฅผ ํ๋ ์์ ์ foundUser๋ฅผ ํน์ํ๊ฒ ์ฒ๋ฆฌํ๊ณ UPDATE ์ฟผ๋ฆฌ๋ฅผ ์ง์ฐ ์ฐ๊ธฐ ๋ฑ๋กํด ๋์ ๊ฒ์ผ๋ก ์ถ์ ๋๋ค. (๋ฐ๋ก ๋น์์ํ์์ผฐ๋ค๋ฉด SELECT ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ์ ๊ฒ..)
nativeQuery๋ก ๊ฐ์ ธ์จ deletedUser๋ ์์์ฑ ์ปจํ ์คํธ์ ๊ด๋ฆฌ๋๋ ์ํ๊ฐ ๋์๊ณ , savedUser๋ ๋น์์ํ๋์๊ธฐ ๋๋ฌธ์ ์ด ๋์ ๋์ผ์ฑ์ด ๊นจ์ง ๊ฒ ๊ฐ๋ค.
Soft Delete์ Hard Delete์ ์ฐจ์ด์ @SQLDelete
DB์ ์ญ์ ๊ตฌํ ๋ฐฉ๋ฒ์ ๋๊ฐ์ง๊ฐ ์๋ค. Soft Delete ๋ฐ์ดํฐ๋ฅผ ์ค์ ๋ก ์ญ์ ํ์ง ์๊ณ , ์ญ์ flag๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ์ด๋ค. Hard Delete ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ค์ ๋ก ์๋น์ค๋ฅผ ๊ตฌํํ ๋์๋ So
hello-backend.tistory.com
JPA, H2 ๋ฐ์ดํฐ ๋ฒ ์ด์ค ๋์๋ฌธ์ ๊ตฌ๋ถ์๋ฌ
๊ฒฐ๋ก spring์์ ๋์๋ฌธ์ ๊ตฌ๋ถ์ ํ์ง ์๋๋ก ํ์ฌ ํต๊ณผํ์์ต๋๋ค. ๊ณต์๋ฌธ์ ๋ด์ฉ์ค ""(๋ฐ์ดํ๋ก ์ด์ค์ผ์ดํ)๋์ง ์์๊ฒ์ ๋๋ฌธ์๋ก ๋ณ๊ฒฝํ์ฌ ์คํํ๋ค๋๊ฒ์ ๋ณด๊ณ ์ด๋ก์ธํ์ฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํ
lahezy.tistory.com
[Spring Boot] Soft Delete ์ ์ฑ ์ ์ํ @SQLDelete์ ์์์ฑ ์ปจํ ์คํธ ๊ฐ์ ์ฌ๋ฐ๋ ์
๐ ๋ชฉ์ฐจ 1. Soft Delete ๋ฐ์ 2. ๋์ผ์ฑ์ด ๊นจ์ง๋ค? 3. ๊ณ ์ฐฐ 1. Soft Delete ๋ฐ์ ๐ Annotation @Entity @Getter @Table(name = "user") @NoArgsConstructor(access = AccessLevel.PROTECTED) @DynamicInsert @SQLRestriction("deleted_at IS NULL") @SQLD
jaeseo0519.tistory.com
'Back-end' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Java Record๋ก DTO๋ฅผ ๋ง๋ค์ด๋ด ์๋ค (0) | 2024.05.01 |
---|---|
[Spring] Meta Annotation์ด๋? (@Target, @Retention ๋ฑ) (0) | 2024.04.29 |
[JPA] CascadeType.REMOVE vs orphanRemoval = true (0) | 2024.04.21 |
[JPA] Cascade ์์์ฑ ์ ์ด (1) | 2024.04.19 |
[JPA] EntityManager ํต์ฌ ๊ธฐ๋ฅ (0) | 2024.04.19 |
๐ซง @SQLDelete
JPA์์ ๊ธฐ๋ณธ์ ์ธ ์ญ์ ๋ Hard Delete๋ก ๋์ด ์๋ค.
์ด ์ญ์ ๋ฐฉ์์ @SQLDelete๋ฅผ ํตํด ์ฟผ๋ฆฌ๋ฅผ ์์ฑํด๋๋ฉด, delete๊ฐ ํธ์ถ๋ ๋ ๋ฐ์ดํฐ๋ฅผ ์ค์ ๋ก ์ญ์ ํ์ง ์๊ณ ๋ฏธ๋ฆฌ ์ ์ํด๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋๋ก ๋ฐฉ์ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค.
Hard Delete
๋ฌผ๋ฆฌ ์ญ์ ๋ผ๊ณ ๋ ํ๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ Delete Query๋ฅผ ๋ ๋ ค ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ค์ ๋ก ์ญ์ ํ๋ค.
Soft Delete
๋ ผ๋ฆฌ ์ญ์ ๋ผ๊ณ ๋ ํ๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ Update Query๋ฅผ ๋ ๋ ค ํด๋น ๋ฐ์ดํฐ๊ฐ ์ญ์ ๋ ๊ฒ์ ํ๋์ ์ปฌ๋ผ์ ์ด์ฉํ์ฌ ๊ตฌ๋ถํ๋ค.
@SQLDelete๋ ๋ ผ๋ฆฌ ์ญ์ ๋ฅผ ์ํ ๊ธฐ๋ฅ์ธ ๊ฒ์ด๋ค.
๐ซง ๋ฌธ์ ๋ฐ๊ฒฌ
ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ค๊ฐ ๋ฐ๊ฒฌํ๊ฒ ๋ ๋ฌธ์ ..
@Test
@DisplayName("ํ์์ ๋
ผ๋ฆฌ ์ญ์ ํ๋ค")
void succeed_to_soft_delete_user() {
// given
User foundUser = userRepository.findById(user.getId()).get();
// when
userRepository.delete(foundUser);
// then
System.out.println(foundUser.getIsDeleted());
}

์์ ํ ์คํธ๋ฅผ ์คํํด ๋ณด๋ฉด UPDATE ์ฟผ๋ฆฌ๋ ์คํ๋์ง ์๊ณ INSERT ์ฟผ๋ฆฌ๋ง ์คํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ํ isDeleted๊ฐ ์ฌ์ ํ false์ธ๋ฐ, ์ด๋ SQLDelete๋ ์์์ฑ ์ปจํ ์คํธ์์ ๊ด๋ฆฌ๋๋ค๊ฐ ํธ๋์ญ์ ์ด ๋๋๊ณ ์ค์ DB์ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ผ๋ ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ๋๋ฌธ์ด๋ค. (์ง์ฐ ์ฐ๊ธฐ, flush๊ฐ ๋ฐ์ํด์ผ ๋จ)
๊ทผ๋ฐ!!! ๋ด๊ฐ ํ์ฐธ ํค๋งธ๋ ๊ฒ์ SELECT ์ฟผ๋ฆฌ๋ ์คํ์ด ์๋๋ค๋ ๊ฑฐ์๋ค.
@Test
@DisplayName("ํ์์ ๋
ผ๋ฆฌ ์ญ์ ํ๋ค")
void succeed_to_soft_delete_user() {
// given
User foundUser = userRepository.findById(user.getId()).get();
// when
userRepository.delete(foundUser);
User deletedUser = userRepository.findById(foundUser.getId()).orElse(null);
// then
System.out.println("isDeleted After delete: " + deletedUser);
}

๋ถ๋ช findById๋ก foundUser๋ ์์ํ๊ฐ ๋์ด์์ ํ ๋ฐ userRepository.findById()์ ๊ฒฐ๊ณผ๊ฐ null์ด ๋์ค๋ ๊ฒ์ด ๋์ ํ ์ดํด๊ฐ ๊ฐ์ง์์๋ค.
findById ์กฐํ๊ฐ ์๋๋๊น flush ํด ์์์ฑ ์ปจํ ์คํธ์ ๋ณ๊ฒฝ ๋ด์ฉ์ DB์ ๋ฐ์ํ ํ ์ด๊ธฐํ ํด๋ณด์๋ค.
๊ทธ ํ ๋ค์ findById ๋ฉ์๋๋ฅผ ํตํด deletedUser๋ฅผ ์์์ฑ ์ปจํ ์คํธ์ ์ฌ๋ ค ๋ณด์๋ค.
@Test
@DisplayName("ํ์์ ๋
ผ๋ฆฌ ์ญ์ ํ๋ค")
void succeed_to_soft_delete_user() {
// given
User foundUser = userRepository.findById(user.getId()).get();
// when
userRepository.delete(foundUser);
em.flush();
em.clear();
User deletedUser = userRepository.findById(user.getId()).get();
// then
assertThat(deletedUser).isNotNull();
System.out.println("๋์ผ์ฑ ๊ฒ์ฆ: " + (foundUser == deletedUser));
System.out.println("foundUser is_deleted: " + foundUser.getIsDeleted());
System.out.println("deletedUser is_deleted: " + deletedUser.getIsDeleted());
}

๊ทธ๋ฐ๋ฐ ๊ฐ์๊ธฐ UPDATE ๋ฌธ์ด ์คํ๋๋๋ฐ, foundUser๋ deletedUser์๋ ๋ฌ๋ฆฌ deleted_at ํ๋๊ฐ ๊ฐฑ์ ๋์ง ์์ ์ด ๋์ ๋์ผ์ฑ์ด ๊นจ์ง๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ด๋ ๊ณง foundUser๋ ์ด๋ ์๊ฐ๋ถํฐ ๋น์์ํ๋ ์ํ์์ ์๋ฏธํ๋ค.
๐ซง ์ ๋น์์ํ ๋๋๋ฐ?!?
์์ํ๋ foundUser๋ฅผ softDete ์ฒ๋ฆฌํ๊ณ , findById()๋ฅผ ํตํด User ์ํฐํฐ๋ฅผ ๊ฐ์ ธ์ค๋ฉด ์ ๋ฐํ๊ฐ์ด null์ด์์๊น?
๋๋ ๋จ์ํ deleted_at ํ๋๊ฐ ์์ ๋๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง SQLDelete๋ฅผ ํตํด ์ํ๋๋ UPDATE ๋ฌธ์ ๋จ์ํ ์์ ์ด ์๋ ์ญ์ ์ ๋ชฉ์ ์ ๊ฐ๋ ์์ ์ด๋ค. ๋ฐ๋ผ์ soft delete๋ฅผ ํ๋ ์์ ์ foundUser๋ฅผ ํน์ํ๊ฒ ์ฒ๋ฆฌํ๊ณ UPDATE ์ฟผ๋ฆฌ๋ฅผ ์ง์ฐ ์ฐ๊ธฐ ๋ฑ๋กํด ๋์ ๊ฒ์ผ๋ก ์ถ์ ๋๋ค. (๋ฐ๋ก ๋น์์ํ์์ผฐ๋ค๋ฉด SELECT ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ์ ๊ฒ..)
nativeQuery๋ก ๊ฐ์ ธ์จ deletedUser๋ ์์์ฑ ์ปจํ ์คํธ์ ๊ด๋ฆฌ๋๋ ์ํ๊ฐ ๋์๊ณ , savedUser๋ ๋น์์ํ๋์๊ธฐ ๋๋ฌธ์ ์ด ๋์ ๋์ผ์ฑ์ด ๊นจ์ง ๊ฒ ๊ฐ๋ค.
Soft Delete์ Hard Delete์ ์ฐจ์ด์ @SQLDelete
DB์ ์ญ์ ๊ตฌํ ๋ฐฉ๋ฒ์ ๋๊ฐ์ง๊ฐ ์๋ค. Soft Delete ๋ฐ์ดํฐ๋ฅผ ์ค์ ๋ก ์ญ์ ํ์ง ์๊ณ , ์ญ์ flag๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ์ด๋ค. Hard Delete ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ค์ ๋ก ์๋น์ค๋ฅผ ๊ตฌํํ ๋์๋ So
hello-backend.tistory.com
JPA, H2 ๋ฐ์ดํฐ ๋ฒ ์ด์ค ๋์๋ฌธ์ ๊ตฌ๋ถ์๋ฌ
๊ฒฐ๋ก spring์์ ๋์๋ฌธ์ ๊ตฌ๋ถ์ ํ์ง ์๋๋ก ํ์ฌ ํต๊ณผํ์์ต๋๋ค. ๊ณต์๋ฌธ์ ๋ด์ฉ์ค ""(๋ฐ์ดํ๋ก ์ด์ค์ผ์ดํ)๋์ง ์์๊ฒ์ ๋๋ฌธ์๋ก ๋ณ๊ฒฝํ์ฌ ์คํํ๋ค๋๊ฒ์ ๋ณด๊ณ ์ด๋ก์ธํ์ฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํ
lahezy.tistory.com
[Spring Boot] Soft Delete ์ ์ฑ ์ ์ํ @SQLDelete์ ์์์ฑ ์ปจํ ์คํธ ๊ฐ์ ์ฌ๋ฐ๋ ์
๐ ๋ชฉ์ฐจ 1. Soft Delete ๋ฐ์ 2. ๋์ผ์ฑ์ด ๊นจ์ง๋ค? 3. ๊ณ ์ฐฐ 1. Soft Delete ๋ฐ์ ๐ Annotation @Entity @Getter @Table(name = "user") @NoArgsConstructor(access = AccessLevel.PROTECTED) @DynamicInsert @SQLRestriction("deleted_at IS NULL") @SQLD
jaeseo0519.tistory.com
'Back-end' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Java Record๋ก DTO๋ฅผ ๋ง๋ค์ด๋ด ์๋ค (0) | 2024.05.01 |
---|---|
[Spring] Meta Annotation์ด๋? (@Target, @Retention ๋ฑ) (0) | 2024.04.29 |
[JPA] CascadeType.REMOVE vs orphanRemoval = true (0) | 2024.04.21 |
[JPA] Cascade ์์์ฑ ์ ์ด (1) | 2024.04.19 |
[JPA] EntityManager ํต์ฌ ๊ธฐ๋ฅ (0) | 2024.04.19 |