Skip to content

Commit 627f8d4

Browse files
authored
[DDING-000] form, form_field soft delete 적용 (#325)
1 parent 8726365 commit 627f8d4

File tree

9 files changed

+109
-38
lines changed

9 files changed

+109
-38
lines changed

src/main/java/ddingdong/ddingdongBE/domain/club/entity/Club.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,8 @@ public void addClubMembers(List<ClubMember> clubMembers) {
128128
this.clubMembers.addAll(clubMembers);
129129
clubMembers.forEach(clubMember -> clubMember.setClubForConvenience(this));
130130
}
131+
132+
public void removeAll(final List<ClubMember> deletedMembers) {
133+
this.clubMembers.removeAll(deletedMembers);
134+
}
131135
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package ddingdong.ddingdongBE.domain.clubmember.repository;
22

33
import ddingdong.ddingdongBE.domain.clubmember.entity.ClubMember;
4+
import java.util.Collection;
5+
import java.util.List;
46
import org.springframework.data.jpa.repository.JpaRepository;
57

68
public interface ClubMemberRepository extends JpaRepository<ClubMember, Long> {
79

10+
List<ClubMember> findByIdIn(Collection<Long> ids);
11+
12+
List<ClubMember> findByClubId(Long clubId);
813
}

src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/ClubMemberService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ public interface ClubMemberService {
1414
void delete(ClubMember clubMember);
1515

1616
void save(ClubMember clubMember);
17+
18+
void updateAll(List<ClubMember> updateClubMemberInfos);
19+
20+
List<ClubMember> getByClubId(Long clubId);
1721
}

src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberServiceImpl.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,22 @@ public AllClubMemberInfoQuery getAllMyClubMember(Long userId) {
4343
@Transactional
4444
public void updateMemberList(UpdateClubMemberListCommand command) {
4545
Club club = clubService.getByUserId(command.userId());
46-
List<ClubMember> updatedClubMembers =
46+
List<ClubMember> updateClubMemberInfos =
4747
excelFileService.extractClubMembersInformation(club, command.clubMemberListFile());
48-
List<ClubMember> clubMembers = club.getClubMembers();
49-
Set<Long> updatedMemberIds = updatedClubMembers.stream()
48+
List<ClubMember> clubMembers = clubMemberService.getByClubId(club.getId());
49+
Set<Long> updatedMemberInfoIds = updateClubMemberInfos.stream()
5050
.map(ClubMember::getId)
5151
.collect(Collectors.toSet());
5252
Set<Long> currentMemberIds = clubMembers.stream()
5353
.map(ClubMember::getId)
5454
.collect(Collectors.toSet());
5555

56-
clubMemberService.saveAll(filterCreatedMembers(updatedClubMembers, updatedMemberIds, currentMemberIds));
57-
clubMemberService.deleteAll(filterDeletedMembers(clubMembers, updatedMemberIds, currentMemberIds));
56+
clubMemberService.saveAll(filterCreatedMembers(updateClubMemberInfos, updatedMemberInfoIds, currentMemberIds));
57+
clubMemberService.updateAll(filterUpdatedMembers(updateClubMemberInfos, updatedMemberInfoIds, currentMemberIds));
58+
59+
List<ClubMember> deletedMembers = filterDeletedMembers(clubMembers, updatedMemberInfoIds, currentMemberIds);
60+
club.removeAll(deletedMembers);
61+
clubMemberService.deleteAll(deletedMembers);
5862
}
5963

6064
@Override
@@ -91,10 +95,20 @@ private List<ClubMember> filterCreatedMembers(List<ClubMember> updatedClubMember
9195
.toList();
9296
}
9397

98+
private List<ClubMember> filterUpdatedMembers(List<ClubMember> updatedClubMembers, Set<Long> updatedMemberIds,
99+
Set<Long> currentMemberIds) {
100+
Set<Long> willUpdateMemberIds = new HashSet<>(currentMemberIds);
101+
willUpdateMemberIds.retainAll(updatedMemberIds);
102+
return updatedClubMembers.stream()
103+
.filter(member -> willUpdateMemberIds.contains(member.getId()))
104+
.toList();
105+
}
106+
94107
private List<ClubMember> filterDeletedMembers(List<ClubMember> clubMembers, Set<Long> updatedMemberIds,
95108
Set<Long> currentMemberIds) {
96109
Set<Long> deletedMemberIds = new HashSet<>(currentMemberIds);
97110
deletedMemberIds.removeAll(updatedMemberIds);
111+
System.out.println(deletedMemberIds);
98112
return clubMembers.stream()
99113
.filter(member -> deletedMemberIds.contains(member.getId()))
100114
.toList();

src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/GeneralClubMemberService.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import ddingdong.ddingdongBE.domain.clubmember.entity.ClubMember;
55
import ddingdong.ddingdongBE.domain.clubmember.repository.ClubMemberRepository;
66
import java.util.List;
7+
import java.util.Map;
8+
import java.util.function.Function;
9+
import java.util.stream.Collectors;
710
import lombok.RequiredArgsConstructor;
811
import org.springframework.stereotype.Service;
912
import org.springframework.transaction.annotation.Transactional;
@@ -30,7 +33,7 @@ public void saveAll(List<ClubMember> clubMembers) {
3033
@Override
3134
@Transactional
3235
public void deleteAll(List<ClubMember> clubMembers) {
33-
clubMemberRepository.deleteAllInBatch(clubMembers);
36+
clubMemberRepository.deleteAll(clubMembers);
3437
}
3538

3639
@Override
@@ -44,4 +47,20 @@ public void delete(ClubMember clubMember) {
4447
public void save(ClubMember clubMember) {
4548
clubMemberRepository.save(clubMember);
4649
}
50+
51+
@Override
52+
@Transactional
53+
public void updateAll(final List<ClubMember> updateClubMemberInfos) {
54+
Map<Long, ClubMember> updatedMemberMap = updateClubMemberInfos.stream()
55+
.collect(Collectors.toMap(ClubMember::getId, Function.identity()));
56+
57+
clubMemberRepository.findByIdIn(updatedMemberMap.keySet())
58+
.forEach(member ->
59+
member.updateInformation(updatedMemberMap.get(member.getId())));
60+
}
61+
62+
@Override
63+
public List<ClubMember> getByClubId(final Long clubId) {
64+
return clubMemberRepository.findByClubId(clubId);
65+
}
4766
}

src/main/java/ddingdong/ddingdongBE/domain/form/entity/Form.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import jakarta.persistence.ManyToOne;
1515
import jakarta.persistence.OneToMany;
1616
import java.time.LocalDate;
17+
import java.time.LocalDateTime;
1718
import java.util.ArrayList;
1819
import java.util.List;
1920
import java.util.Map;
@@ -23,10 +24,14 @@
2324
import lombok.Builder;
2425
import lombok.Getter;
2526
import lombok.NoArgsConstructor;
27+
import org.hibernate.annotations.SQLDelete;
28+
import org.hibernate.annotations.SQLRestriction;
2629

2730
@Entity
2831
@NoArgsConstructor(access = AccessLevel.PROTECTED)
2932
@Getter
33+
@SQLDelete(sql = "update form set deleted_at = CURRENT_TIMESTAMP where id=?")
34+
@SQLRestriction("deleted_at IS NULL")
3035
public class Form extends BaseEntity {
3136

3237
@Id
@@ -54,6 +59,9 @@ public class Form extends BaseEntity {
5459
@ManyToOne(fetch = FetchType.LAZY)
5560
private Club club;
5661

62+
@Column(columnDefinition = "TIMESTAMP")
63+
private LocalDateTime deletedAt;
64+
5765
@OneToMany(mappedBy = "form", cascade = CascadeType.ALL, orphanRemoval = true)
5866
private List<FormField> formFields = new ArrayList<>();
5967

src/main/java/ddingdong/ddingdongBE/domain/form/entity/FormField.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,20 @@
1212
import jakarta.persistence.GenerationType;
1313
import jakarta.persistence.Id;
1414
import jakarta.persistence.ManyToOne;
15+
import java.time.LocalDateTime;
1516
import java.util.List;
1617
import lombok.AccessLevel;
1718
import lombok.Builder;
1819
import lombok.Getter;
1920
import lombok.NoArgsConstructor;
21+
import org.hibernate.annotations.SQLDelete;
22+
import org.hibernate.annotations.SQLRestriction;
2023

2124
@Entity
2225
@NoArgsConstructor(access = AccessLevel.PROTECTED)
2326
@Getter
27+
@SQLDelete(sql = "update form_field set deleted_at = CURRENT_TIMESTAMP where id=?")
28+
@SQLRestriction("deleted_at IS NULL")
2429
public class FormField extends BaseEntity {
2530

2631
@Id
@@ -49,6 +54,9 @@ public class FormField extends BaseEntity {
4954
@ManyToOne(fetch = FetchType.LAZY)
5055
private Form form;
5156

57+
@Column(columnDefinition = "TIMESTAMP")
58+
private LocalDateTime deletedAt;
59+
5260
@Builder
5361
private FormField(
5462
Long id,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE form
2+
ADD deleted_at timestamp NULL;
3+
4+
ALTER TABLE form_field
5+
ADD deleted_at timestamp NULL;

src/test/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberServiceTest.java

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,21 @@ class FacadeCentralClubMemberServiceTest extends TestContainerSupport {
6262

6363
@DisplayName("엑셀 파일을 통해 동아리원 명단을 수정한다.")
6464
@Test
65-
void updateClubMemberList() throws IOException {
66-
//given
65+
void updateAllClubMemberList() throws IOException {
66+
// given
67+
User user = UserFixture.createClubUser();
68+
User savedUser = userRepository.save(user);
69+
Club club = ClubFixture.createClub(savedUser);
70+
Club savedClub = clubRepository.save(club);
71+
72+
ClubMember member1 = ClubMember.builder().club(savedClub).name("기존멤버1").build();
73+
ClubMember member2 = ClubMember.builder().club(savedClub).name("기존멤버2").build();
74+
ClubMember member3 = ClubMember.builder().club(savedClub).name("기존멤버3").build();
75+
76+
List<ClubMember> existingMembers = clubMemberRepository.saveAll(List.of(member1, member2, member3));
77+
club.addClubMembers(existingMembers);
78+
79+
// 엑셀 파일 생성 (기존 멤버 중 1, 2번만 유지하고 3번 삭제)
6780
ByteArrayOutputStream out = new ByteArrayOutputStream();
6881
Workbook workbook = new XSSFWorkbook();
6982
Sheet sheet = workbook.createSheet("Members");
@@ -75,21 +88,24 @@ void updateClubMemberList() throws IOException {
7588
header.createCell(4).setCellValue("비교(임원진) - 영어만");
7689
header.createCell(5).setCellValue("학과(부)");
7790

91+
// 기존 멤버 1번만 유지
7892
Row row1 = sheet.createRow(1);
79-
row1.createCell(0).setCellValue(1);
80-
row1.createCell(1).setCellValue("5uhwann");
93+
row1.createCell(0).setCellValue(existingMembers.get(0).getId());
94+
row1.createCell(1).setCellValue("수정된멤버1");
8195
row1.createCell(2).setCellValue("60001234");
8296
row1.createCell(3).setCellValue("010-1234-5678");
83-
row1.createCell(4).setCellValue("LEADER");
84-
row1.createCell(5).setCellValue("융합소프트웨어학부");
97+
row1.createCell(4).setCellValue("MEMBER");
98+
row1.createCell(5).setCellValue("컴퓨터공학과");
8599

100+
// 기존 멤버 2번만 유지
86101
Row row2 = sheet.createRow(2);
87-
row2.createCell(0).setCellValue(6);
88-
row2.createCell(1).setCellValue("5uhwann");
89-
row2.createCell(2).setCellValue(60001234);
90-
row2.createCell(3).setCellValue("010-1234-5678");
91-
row2.createCell(4).setCellValue("LEADER");
92-
row2.createCell(5).setCellValue("융합소프트웨어학부");
102+
row2.createCell(0).setCellValue(existingMembers.get(1).getId());
103+
row2.createCell(1).setCellValue("수정된멤버2");
104+
row2.createCell(2).setCellValue("60002345");
105+
row2.createCell(3).setCellValue("010-2345-6789");
106+
row2.createCell(4).setCellValue("MEMBER");
107+
row2.createCell(5).setCellValue("컴퓨터공학과");
108+
93109
workbook.write(out);
94110
workbook.close();
95111

@@ -101,37 +117,25 @@ void updateClubMemberList() throws IOException {
101117
in
102118
);
103119

104-
User savedUser = userRepository.save(fixtureMonkey.giveMeOne(User.class));
105-
Club savedClub = clubRepository.save(fixtureMonkey.giveMeBuilder(Club.class)
106-
.set("user", savedUser)
107-
.set("score", Score.from(BigDecimal.ZERO))
108-
.set("clubMembers", List.of())
109-
.set("deletedAt", null)
110-
.sample());
111-
List<ClubMember> clubMembers = fixtureMonkey.giveMeBuilder(ClubMember.class)
112-
.set("club", savedClub)
113-
.set("deletedAt", null)
114-
.sampleList(5);
115-
clubMemberRepository.saveAll(clubMembers);
116-
entityManager.flush();
117-
entityManager.clear();
118-
119120
UpdateClubMemberListCommand command = UpdateClubMemberListCommand.builder()
120121
.userId(savedUser.getId())
121122
.clubMemberListFile(validExcelFile)
122123
.build();
123124

124-
//when
125+
// when
125126
facadeCentralClubMemberService.updateMemberList(command);
126127

127-
//then
128-
List<ClubMember> updatedClubMemberList = clubMemberRepository.findAll();
129-
assertThat(updatedClubMemberList.size()).isEqualTo(2);
128+
// then
129+
List<ClubMember> remainingMembers = clubMemberRepository.findAll();
130+
assertThat(remainingMembers).hasSize(2); // member3는 soft delete됨
131+
assertThat(remainingMembers)
132+
.extracting(ClubMember::getName)
133+
.containsExactlyInAnyOrder("수정된멤버1", "수정된멤버2");
130134
}
131135

132136
@DisplayName("동아리원 정보를 수정한다.")
133137
@Test
134-
void update() {
138+
void updateAll() {
135139
//given
136140
User savedUser = userRepository.save(fixtureMonkey.giveMeOne(User.class));
137141
Club savedClub = clubRepository.save(fixtureMonkey.giveMeBuilder(Club.class)

0 commit comments

Comments
 (0)