Skip to content

Commit 6bbdc5c

Browse files
committed
feat: 피드 수정/삭제시 참조를 잃은 태그 또한 삭제
1 parent be6d93b commit 6bbdc5c

4 files changed

Lines changed: 63 additions & 1 deletion

File tree

NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/post/dao/PostTagRepository.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.twogether.nbe_5_7_2_02team.post.domain.PostTag;
55

66
import org.springframework.data.jpa.repository.JpaRepository;
7+
import org.springframework.data.jpa.repository.Query;
78

89
import java.util.List;
910

@@ -12,4 +13,7 @@ public interface PostTagRepository extends JpaRepository<PostTag, Long> {
1213
void deleteAllByPost(Post post);
1314

1415
List<PostTag> findAllByPost(Post post);
15-
}
16+
17+
@Query("SELECT DISTINCT pt.tag.id FROM PostTag pt")
18+
List<Long> findAllTagIds();
19+
}

NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/post/service/PostService.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.twogether.nbe_5_7_2_02team.post.util.ImageUploader;
2626
import io.twogether.nbe_5_7_2_02team.post.util.PostMapper;
2727

28+
import io.twogether.nbe_5_7_2_02team.tag.dao.TagRepository;
2829
import lombok.RequiredArgsConstructor;
2930

3031
import org.springframework.security.core.userdetails.UserDetails;
@@ -46,6 +47,7 @@ public class PostService {
4647
private final ImageUploader imageUploader;
4748
private final ChatRepository chatRepository;
4849
private final LikesRepository likesRepository;
50+
private final TagRepository tagRepository;
4951

5052
@Transactional
5153
public PostResponse createPost(PostCreateRequest request, Long memberId) {
@@ -96,6 +98,7 @@ public PostResponse updatePost(Long postId, PostUpdateRequest request, Long memb
9698

9799
if (request.getTags() != null) {
98100
postTagRepository.deleteAllByPost(updatePost);
101+
deleteUnusedTags();
99102

100103
List<PostTag> newTags = postMapper.toPostTags(updatePost, request.getTags());
101104
postTagRepository.saveAll(newTags);
@@ -119,6 +122,12 @@ public void deletePost(Long postId, Long memberId) {
119122
chatRepository.deleteByPost(deletePost);
120123
imageUploader.deletePostImageByFolder(deletePost.getId());
121124
postRepository.delete(deletePost);
125+
deleteUnusedTags();
126+
}
127+
128+
private void deleteUnusedTags() {
129+
List<Long> referredTagIds = postTagRepository.findAllTagIds();
130+
tagRepository.deleteUnusedTags(referredTagIds);
122131
}
123132

124133
@Transactional(readOnly = true)

NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/tag/dao/TagRepository.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@
22

33
import io.twogether.nbe_5_7_2_02team.tag.domain.Tag;
44

5+
import java.util.List;
56
import org.springframework.data.jpa.repository.JpaRepository;
67

78
import java.util.Optional;
9+
import org.springframework.data.jpa.repository.Modifying;
10+
import org.springframework.data.jpa.repository.Query;
811

912
public interface TagRepository extends JpaRepository<Tag, Long> {
1013

1114
Optional<Tag> findByName(String name);
15+
16+
@Query(
17+
"""
18+
DELETE FROM Tag t
19+
WHERE t.id NOT IN :referredTagIds
20+
"""
21+
)
22+
@Modifying
23+
void deleteUnusedTags(List<Long> referredTagIds);
1224
}

NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/browser/PostBrowserSuccessTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import static io.twogether.nbe_5_7_2_02team.post.domain.RecruitmentStatus.NONE;
55
import static io.twogether.nbe_5_7_2_02team.post.domain.RecruitmentStatus.RECRUITING;
66

7+
import static org.assertj.core.api.Assertions.assertThat;
78
import static org.hamcrest.Matchers.containsInAnyOrder;
9+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
810
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
911
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
1012
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
@@ -17,8 +19,10 @@
1719
import io.twogether.nbe_5_7_2_02team.member.dao.MemberRepository;
1820
import io.twogether.nbe_5_7_2_02team.member.domain.Member;
1921
import io.twogether.nbe_5_7_2_02team.oauth.dto.common.TokenPair;
22+
import io.twogether.nbe_5_7_2_02team.post.dao.PostRepository;
2023
import io.twogether.nbe_5_7_2_02team.post.domain.RecruitmentStatus;
2124

25+
import io.twogether.nbe_5_7_2_02team.tag.dao.TagRepository;
2226
import lombok.AllArgsConstructor;
2327

2428
import org.junit.jupiter.api.DisplayName;
@@ -35,6 +39,10 @@
3539
public class PostBrowserSuccessTest extends BrowserTestTemplate {
3640

3741
@Autowired MemberRepository memberRepository;
42+
@Autowired
43+
private TagRepository tagRepository;
44+
@Autowired
45+
private PostRepository postRepository;
3846

3947
@AllArgsConstructor
4048
static class PostCreateRequest {
@@ -234,6 +242,35 @@ void getPostsPaging() throws Exception {
234242
jsonPath("$.posts[0].post_id").value(1));
235243
}
236244

245+
@Test
246+
@DataSet(
247+
value = {
248+
"datasets/v2/member.yml",
249+
"datasets/v2/post.yml",
250+
"datasets/v2/tag.yml",
251+
},
252+
cleanBefore = true,
253+
cleanAfter = true)
254+
@DisplayName("DELETE: /api/posts/{postId} 회원 접근 - 게시글 삭제 시 연관 게시글이 없는 태그 또한 삭제")
255+
void deletePostWithUnusedTags() throws Exception {
256+
// given
257+
long targetMemberId = 1L;
258+
long targetPostId = 2L;
259+
TokenPair tokenPair = getTokenPair(targetMemberId);
260+
261+
// when
262+
mockMvc.perform(
263+
delete("/api/posts/" + targetPostId)
264+
.header("Authorization", "Bearer " + tokenPair.getAccessToken())
265+
).andExpect(
266+
status().isOk()
267+
);
268+
269+
// then : 2번 게시글 삭제 시 2번 태그는 참조를 잃어 삭제되어야 함
270+
assertThat(postRepository.findById(targetPostId).isPresent()).isFalse();
271+
assertThat(tagRepository.findById(2L).isPresent()).isFalse();
272+
}
273+
237274
private TokenPair getTokenPair(Long memberId) {
238275
Member member = memberRepository.findById(memberId).orElseThrow();
239276
return jwtTokenProvider.generateTokenPair(member);

0 commit comments

Comments
 (0)