From aa8859adb09c136d02fcc06173ecb4a39d48969c Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Sun, 10 Aug 2025 23:41:46 +0900 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20mentoring=5Fid=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=BC=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=9C=A0=EB=8B=88?= =?UTF-8?q?=ED=81=AC=20=EC=A0=9C=EC=95=BD=EC=A1=B0=EA=B1=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 멘토링의 경우에만 mentoringId가 존재하므로 long이 아닌 Long으로 설정 --- .../solidconnection/chat/domain/ChatRoom.java | 17 +++++++++++++++++ .../V28__add_mentoring_id_to_chat_room.sql | 6 ++++++ 2 files changed, 23 insertions(+) create mode 100644 src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql diff --git a/src/main/java/com/example/solidconnection/chat/domain/ChatRoom.java b/src/main/java/com/example/solidconnection/chat/domain/ChatRoom.java index e8e7a3ebb..849cfe4f5 100644 --- a/src/main/java/com/example/solidconnection/chat/domain/ChatRoom.java +++ b/src/main/java/com/example/solidconnection/chat/domain/ChatRoom.java @@ -2,11 +2,14 @@ import com.example.solidconnection.common.BaseEntity; import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import java.util.ArrayList; import java.util.List; import lombok.AccessLevel; @@ -17,6 +20,12 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(uniqueConstraints = { + @UniqueConstraint( + name = "uk_chat_room_mentoring_id", + columnNames = {"mentoring_id"} + ) +}) public class ChatRoom extends BaseEntity { @Id @@ -25,6 +34,9 @@ public class ChatRoom extends BaseEntity { private boolean isGroup = false; + @Column(name = "mentoring_id") + private Long mentoringId; + @OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL) @BatchSize(size = 10) private final List chatParticipants = new ArrayList<>(); @@ -35,4 +47,9 @@ public class ChatRoom extends BaseEntity { public ChatRoom(boolean isGroup) { this.isGroup = isGroup; } + + public ChatRoom(Long mentoringId, boolean isGroup) { + this.mentoringId = mentoringId; + this.isGroup = isGroup; + } } diff --git a/src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql b/src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql new file mode 100644 index 000000000..05e195358 --- /dev/null +++ b/src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql @@ -0,0 +1,6 @@ +ALTER TABLE chat_room + ADD COLUMN mentoring_id BIGINT; + +ALTER TABLE chat_room + ADD CONSTRAINT uk_chat_room_mentoring_id + UNIQUE (mentoring_id); From 3b089eac13edce8fa2a3a9c505f1009408113ec9 Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Sun, 10 Aug 2025 23:42:31 +0900 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20=EB=A9=98=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EC=B1=84=ED=8C=85=EB=B0=A9=20=EC=83=9D=EC=84=B1=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/repository/ChatRoomRepository.java | 3 +++ .../solidconnection/chat/service/ChatService.java | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/com/example/solidconnection/chat/repository/ChatRoomRepository.java b/src/main/java/com/example/solidconnection/chat/repository/ChatRoomRepository.java index dd5193abf..a7f4b2765 100644 --- a/src/main/java/com/example/solidconnection/chat/repository/ChatRoomRepository.java +++ b/src/main/java/com/example/solidconnection/chat/repository/ChatRoomRepository.java @@ -2,6 +2,7 @@ import com.example.solidconnection.chat.domain.ChatRoom; import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -33,4 +34,6 @@ SELECT COUNT(cm) FROM ChatMessage cm AND (crs.updatedAt IS NULL OR cm.createdAt > crs.updatedAt) """) long countUnreadMessages(@Param("chatRoomId") long chatRoomId, @Param("userId") long userId); + + Optional findByMentoringId(long mentoringId); } diff --git a/src/main/java/com/example/solidconnection/chat/service/ChatService.java b/src/main/java/com/example/solidconnection/chat/service/ChatService.java index c378f6b50..1a2570bce 100644 --- a/src/main/java/com/example/solidconnection/chat/service/ChatService.java +++ b/src/main/java/com/example/solidconnection/chat/service/ChatService.java @@ -124,4 +124,18 @@ public void markChatMessagesAsRead(long siteUserId, long roomId) { chatReadStatusRepository.upsertReadStatus(roomId, participant.getId()); } + + @Transactional + public void createMentoringChatRoom(Long mentoringId, Long mentorId, Long menteeId) { + Optional existingChatRoom = chatRoomRepository.findByMentoringId(mentoringId); + if (existingChatRoom.isPresent()) { + return; + } + + ChatRoom chatRoom = new ChatRoom(mentoringId, false); + chatRoom = chatRoomRepository.save(chatRoom); + ChatParticipant mentorParticipant = new ChatParticipant(mentorId, chatRoom); + ChatParticipant menteeParticipant = new ChatParticipant(menteeId, chatRoom); + chatParticipantRepository.saveAll(List.of(mentorParticipant, menteeParticipant)); + } } From 763e699549670e82421d9754f3e3823673357ed7 Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Sun, 10 Aug 2025 23:43:06 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20=EB=A9=98=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8=20=EC=8B=9C=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=20=ED=98=B8=EC=B6=9C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mentor/dto/MentoringApprovedEvent.java | 12 ++++++++++ .../service/MentoringCommandService.java | 4 ++++ .../mentor/service/MentoringEventHandler.java | 24 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 src/main/java/com/example/solidconnection/mentor/dto/MentoringApprovedEvent.java create mode 100644 src/main/java/com/example/solidconnection/mentor/service/MentoringEventHandler.java diff --git a/src/main/java/com/example/solidconnection/mentor/dto/MentoringApprovedEvent.java b/src/main/java/com/example/solidconnection/mentor/dto/MentoringApprovedEvent.java new file mode 100644 index 000000000..4909a5c85 --- /dev/null +++ b/src/main/java/com/example/solidconnection/mentor/dto/MentoringApprovedEvent.java @@ -0,0 +1,12 @@ +package com.example.solidconnection.mentor.dto; + +public record MentoringApprovedEvent( + long mentoringId, + long mentorId, + long menteeId +) { + + public static MentoringApprovedEvent of(long mentoringId, long mentorId, long menteeId) { + return new MentoringApprovedEvent(mentoringId, mentorId, menteeId); + } +} diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java index dd4e98936..15a1e2507 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java @@ -11,11 +11,13 @@ import com.example.solidconnection.mentor.domain.Mentoring; import com.example.solidconnection.mentor.dto.MentoringApplyRequest; import com.example.solidconnection.mentor.dto.MentoringApplyResponse; +import com.example.solidconnection.mentor.dto.MentoringApprovedEvent; import com.example.solidconnection.mentor.dto.MentoringConfirmRequest; import com.example.solidconnection.mentor.dto.MentoringConfirmResponse; import com.example.solidconnection.mentor.repository.MentorRepository; import com.example.solidconnection.mentor.repository.MentoringRepository; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,6 +27,7 @@ public class MentoringCommandService { private final MentoringRepository mentoringRepository; private final MentorRepository mentorRepository; + private final ApplicationEventPublisher eventPublisher; @Transactional public MentoringApplyResponse applyMentoring(long siteUserId, MentoringApplyRequest mentoringApplyRequest) { @@ -48,6 +51,7 @@ public MentoringConfirmResponse confirmMentoring(long siteUserId, long mentoring if (mentoringConfirmRequest.status() == VerifyStatus.APPROVED) { mentor.increaseMenteeCount(); + eventPublisher.publishEvent(MentoringApprovedEvent.of(mentoringId, mentor.getSiteUserId(), mentoring.getMenteeId())); } return MentoringConfirmResponse.from(mentoring); diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringEventHandler.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringEventHandler.java new file mode 100644 index 000000000..f644c2f35 --- /dev/null +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringEventHandler.java @@ -0,0 +1,24 @@ +package com.example.solidconnection.mentor.service; + +import com.example.solidconnection.chat.service.ChatService; +import com.example.solidconnection.mentor.dto.MentoringApprovedEvent; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +@Component +@RequiredArgsConstructor +public class MentoringEventHandler { + + private final ChatService chatService; + + @EventListener + @Async + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void handleMentoringApproved(MentoringApprovedEvent event) { + chatService.createMentoringChatRoom(event.mentoringId(), event.mentorId(), event.menteeId()); + } +} From 0a821ca96eb58235c9cc85445d6df785ad20c51d Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Sun, 10 Aug 2025 23:43:19 +0900 Subject: [PATCH 04/12] =?UTF-8?q?test:=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A4=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ChatRoomRepositoryForTest.java | 29 +++++++++++ .../service/MentoringCommandServiceTest.java | 50 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java diff --git a/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java b/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java new file mode 100644 index 000000000..c42fc51be --- /dev/null +++ b/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java @@ -0,0 +1,29 @@ +package com.example.solidconnection.chat.repository; + +import com.example.solidconnection.chat.domain.ChatRoom; +import io.lettuce.core.dynamic.annotation.Param; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface ChatRoomRepositoryForTest extends JpaRepository { + + @Query(""" + SELECT cr FROM ChatRoom cr + LEFT JOIN FETCH cr.chatParticipants cp + WHERE cr.isGroup = false + AND EXISTS ( + SELECT 1 FROM ChatParticipant cp1 + WHERE cp1.chatRoom = cr AND cp1.siteUserId = :mentorId + ) + AND EXISTS ( + SELECT 1 FROM ChatParticipant cp2 + WHERE cp2.chatRoom = cr AND cp2.siteUserId = :menteeId + ) + AND ( + SELECT COUNT(cp3) FROM ChatParticipant cp3 + WHERE cp3.chatRoom = cr + ) = 2 + """) + Optional findOneOnOneChatRoomByParticipants(@Param("mentorId") long mentorId, @Param("menteeId") long menteeId); +} diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java index a92925653..766542621 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java @@ -7,6 +7,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; +import com.example.solidconnection.chat.domain.ChatParticipant; +import com.example.solidconnection.chat.domain.ChatRoom; +import com.example.solidconnection.chat.repository.ChatRoomRepositoryForTest; import com.example.solidconnection.common.VerifyStatus; import com.example.solidconnection.common.exception.CustomException; import com.example.solidconnection.mentor.domain.Mentor; @@ -22,6 +25,8 @@ import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.fixture.SiteUserFixture; import com.example.solidconnection.support.TestContainerSpringBootTest; +import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -41,6 +46,9 @@ class MentoringCommandServiceTest { @Autowired private MentoringRepository mentoringRepository; + @Autowired + private ChatRoomRepositoryForTest chatRoomRepositoryForTest; + @Autowired private SiteUserFixture siteUserFixture; @@ -115,6 +123,31 @@ class 멘토링_승인_거절_테스트 { ); } + @Test + void 멘토링_승인시_채팅방이_자동으로_생성된다() { + // given + Mentoring mentoring = mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser.getId()); + MentoringConfirmRequest request = new MentoringConfirmRequest(VerifyStatus.APPROVED); + + Optional beforeChatRoom = chatRoomRepositoryForTest.findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()); + assertThat(beforeChatRoom).isEmpty(); + + // when + mentoringCommandService.confirmMentoring(mentorUser1.getId(), mentoring.getId(), request); + + // then + ChatRoom afterChatRoom = chatRoomRepositoryForTest + .findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()) + .orElseThrow(); + List participantIds = afterChatRoom.getChatParticipants().stream() + .map(ChatParticipant::getSiteUserId) + .toList(); + assertAll( + () -> assertThat(afterChatRoom.isGroup()).isFalse(), + () -> assertThat(participantIds).containsExactly(mentorUser1.getId(), menteeUser.getId()) + ); + } + @Test void 멘토링을_성공적으로_거절한다() { // given @@ -137,6 +170,23 @@ class 멘토링_승인_거절_테스트 { ); } + @Test + void 멘토링_거절시_채팅방이_자동으로_생성되지_않는다() { + // given + Mentoring mentoring = mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser.getId()); + MentoringConfirmRequest request = new MentoringConfirmRequest(VerifyStatus.REJECTED); + + Optional beforeChatRoom = chatRoomRepositoryForTest.findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()); + assertThat(beforeChatRoom).isEmpty(); + + // when + mentoringCommandService.confirmMentoring(mentorUser1.getId(), mentoring.getId(), request); + + // then + Optional afterChatRoom = chatRoomRepositoryForTest.findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()); + assertThat(afterChatRoom).isEmpty(); + } + @Test void 다른_멘토의_멘토링을_승인할_수_없다() { // given From 1cd2390fddffa5ed9a9c9eae13e100d1abbc59c3 Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Mon, 11 Aug 2025 23:17:14 +0900 Subject: [PATCH 05/12] =?UTF-8?q?refactor:=20@TransactionalEventListener?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solidconnection/mentor/service/MentoringEventHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringEventHandler.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringEventHandler.java index f644c2f35..920ff007f 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringEventHandler.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringEventHandler.java @@ -3,11 +3,11 @@ import com.example.solidconnection.chat.service.ChatService; import com.example.solidconnection.mentor.dto.MentoringApprovedEvent; import lombok.RequiredArgsConstructor; -import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.event.TransactionalEventListener; @Component @RequiredArgsConstructor @@ -15,9 +15,9 @@ public class MentoringEventHandler { private final ChatService chatService; - @EventListener @Async @Transactional(propagation = Propagation.REQUIRES_NEW) + @TransactionalEventListener public void handleMentoringApproved(MentoringApprovedEvent event) { chatService.createMentoringChatRoom(event.mentoringId(), event.mentorId(), event.menteeId()); } From cee0914a58eb4a9991c4ff96544dc6fcc882e5d4 Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Mon, 11 Aug 2025 23:18:35 +0900 Subject: [PATCH 06/12] =?UTF-8?q?fix:=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20import=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/repository/ChatRoomRepositoryForTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java b/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java index c42fc51be..9cebe3fd5 100644 --- a/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java +++ b/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java @@ -1,10 +1,10 @@ package com.example.solidconnection.chat.repository; import com.example.solidconnection.chat.domain.ChatRoom; -import io.lettuce.core.dynamic.annotation.Param; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface ChatRoomRepositoryForTest extends JpaRepository { From 9cc36c9b5a525ff3cd4c9d85cf5ba69b8d78b2c6 Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Mon, 11 Aug 2025 23:19:14 +0900 Subject: [PATCH 07/12] =?UTF-8?q?refactor:=20DISTINCT=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=98=EC=97=AC=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/repository/ChatRoomRepositoryForTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java b/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java index 9cebe3fd5..7605453c6 100644 --- a/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java +++ b/src/test/java/com/example/solidconnection/chat/repository/ChatRoomRepositoryForTest.java @@ -9,7 +9,7 @@ public interface ChatRoomRepositoryForTest extends JpaRepository { @Query(""" - SELECT cr FROM ChatRoom cr + SELECT DISTINCT cr FROM ChatRoom cr LEFT JOIN FETCH cr.chatParticipants cp WHERE cr.isGroup = false AND EXISTS ( From c59a31465bb62676d455d775486284534ff97276 Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Mon, 11 Aug 2025 23:20:38 +0900 Subject: [PATCH 08/12] =?UTF-8?q?refactor:=20@Column=EC=97=90=20=EC=9C=A0?= =?UTF-8?q?=EB=8B=88=ED=81=AC=ED=82=A4=20=EC=84=A4=EC=A0=95=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/solidconnection/chat/domain/ChatRoom.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/main/java/com/example/solidconnection/chat/domain/ChatRoom.java b/src/main/java/com/example/solidconnection/chat/domain/ChatRoom.java index 849cfe4f5..fc159c2cd 100644 --- a/src/main/java/com/example/solidconnection/chat/domain/ChatRoom.java +++ b/src/main/java/com/example/solidconnection/chat/domain/ChatRoom.java @@ -8,8 +8,6 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; import java.util.ArrayList; import java.util.List; import lombok.AccessLevel; @@ -20,12 +18,6 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(uniqueConstraints = { - @UniqueConstraint( - name = "uk_chat_room_mentoring_id", - columnNames = {"mentoring_id"} - ) -}) public class ChatRoom extends BaseEntity { @Id @@ -34,7 +26,7 @@ public class ChatRoom extends BaseEntity { private boolean isGroup = false; - @Column(name = "mentoring_id") + @Column(name = "mentoring_id", unique = true) private Long mentoringId; @OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL) From 66486184696c605b6976e8be79d8bb3a66e5211f Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Mon, 11 Aug 2025 23:24:19 +0900 Subject: [PATCH 09/12] =?UTF-8?q?refactor:=20fk=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/migration/V28__add_mentoring_id_to_chat_room.sql | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql b/src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql index 05e195358..f4ab8d815 100644 --- a/src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql +++ b/src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql @@ -1,6 +1,5 @@ ALTER TABLE chat_room - ADD COLUMN mentoring_id BIGINT; + ADD COLUMN mentoring_id BIGINT, +ADD CONSTRAINT uk_chat_room_mentoring_id UNIQUE (mentoring_id), +ADD CONSTRAINT fk_chat_room_mentoring_id FOREIGN KEY (mentoring_id) REFERENCES mentoring(id); -ALTER TABLE chat_room - ADD CONSTRAINT uk_chat_room_mentoring_id - UNIQUE (mentoring_id); From 49ad5252440c05a79666fcdde74cd4690a5d8625 Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Mon, 11 Aug 2025 23:26:44 +0900 Subject: [PATCH 10/12] =?UTF-8?q?refactor:=20find=20->=20exists=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=ED=95=98=EC=97=AC=20=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solidconnection/chat/repository/ChatRoomRepository.java | 3 +-- .../com/example/solidconnection/chat/service/ChatService.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/solidconnection/chat/repository/ChatRoomRepository.java b/src/main/java/com/example/solidconnection/chat/repository/ChatRoomRepository.java index a7f4b2765..ad815dbe1 100644 --- a/src/main/java/com/example/solidconnection/chat/repository/ChatRoomRepository.java +++ b/src/main/java/com/example/solidconnection/chat/repository/ChatRoomRepository.java @@ -2,7 +2,6 @@ import com.example.solidconnection.chat.domain.ChatRoom; import java.util.List; -import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -35,5 +34,5 @@ SELECT COUNT(cm) FROM ChatMessage cm """) long countUnreadMessages(@Param("chatRoomId") long chatRoomId, @Param("userId") long userId); - Optional findByMentoringId(long mentoringId); + boolean existsByMentoringId(long mentoringId); } diff --git a/src/main/java/com/example/solidconnection/chat/service/ChatService.java b/src/main/java/com/example/solidconnection/chat/service/ChatService.java index a94152176..4a9c02eed 100644 --- a/src/main/java/com/example/solidconnection/chat/service/ChatService.java +++ b/src/main/java/com/example/solidconnection/chat/service/ChatService.java @@ -165,8 +165,7 @@ public void sendChatMessage(ChatMessageSendRequest chatMessageSendRequest, long @Transactional public void createMentoringChatRoom(Long mentoringId, Long mentorId, Long menteeId) { - Optional existingChatRoom = chatRoomRepository.findByMentoringId(mentoringId); - if (existingChatRoom.isPresent()) { + if (chatRoomRepository.existsByMentoringId(mentoringId)) { return; } From 72a35575edca33874358b7d6611762ae822ae4d8 Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Tue, 12 Aug 2025 19:21:27 +0900 Subject: [PATCH 11/12] =?UTF-8?q?test:=20=EB=B9=84=EB=8F=99=EA=B8=B0=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=B2=98=EB=A6=AC=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=EA=B9=8C=EC=A7=80=20=EB=8C=80=EA=B8=B0=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9E=AC=EC=8B=9C=EB=8F=84=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mentor/service/MentoringCommandServiceTest.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java index 766542621..688f2aa2d 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java @@ -6,6 +6,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; +import static org.testcontainers.shaded.org.awaitility.Awaitility.await; import com.example.solidconnection.chat.domain.ChatParticipant; import com.example.solidconnection.chat.domain.ChatRoom; @@ -25,6 +26,7 @@ import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.fixture.SiteUserFixture; import com.example.solidconnection.support.TestContainerSpringBootTest; +import java.time.Duration; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; @@ -136,9 +138,14 @@ class 멘토링_승인_거절_테스트 { mentoringCommandService.confirmMentoring(mentorUser1.getId(), mentoring.getId(), request); // then - ChatRoom afterChatRoom = chatRoomRepositoryForTest - .findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()) + ChatRoom afterChatRoom = await() + .atMost(Duration.ofSeconds(3)) + .pollInterval(Duration.ofMillis(100)) + .until(() -> chatRoomRepositoryForTest + .findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()), + Optional::isPresent) .orElseThrow(); + List participantIds = afterChatRoom.getChatParticipants().stream() .map(ChatParticipant::getSiteUserId) .toList(); From 980be9fb8e16a54b9f69c80d663267665f2278fc Mon Sep 17 00:00:00 2001 From: Gyuhyeok99 Date: Tue, 12 Aug 2025 20:08:21 +0900 Subject: [PATCH 12/12] =?UTF-8?q?test:=20awaitility:4.2.0=20=EB=8F=84?= =?UTF-8?q?=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../mentor/service/MentoringCommandServiceTest.java | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 2de93e064..91cc2e77d 100644 --- a/build.gradle +++ b/build.gradle @@ -62,6 +62,7 @@ dependencies { testImplementation 'org.testcontainers:mysql' testImplementation 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.awaitility:awaitility:4.2.0' // Etc implementation 'org.hibernate.validator:hibernate-validator' diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java index 688f2aa2d..058388d51 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java @@ -6,8 +6,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; -import static org.testcontainers.shaded.org.awaitility.Awaitility.await; - +import static org.awaitility.Awaitility.await; import com.example.solidconnection.chat.domain.ChatParticipant; import com.example.solidconnection.chat.domain.ChatRoom; import com.example.solidconnection.chat.repository.ChatRoomRepositoryForTest; @@ -139,7 +138,7 @@ class 멘토링_승인_거절_테스트 { // then ChatRoom afterChatRoom = await() - .atMost(Duration.ofSeconds(3)) + .atMost(Duration.ofSeconds(5)) .pollInterval(Duration.ofMillis(100)) .until(() -> chatRoomRepositoryForTest .findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()), @@ -190,8 +189,16 @@ class 멘토링_승인_거절_테스트 { mentoringCommandService.confirmMentoring(mentorUser1.getId(), mentoring.getId(), request); // then + await() + .pollInterval(Duration.ofMillis(100)) + .during(Duration.ofSeconds(1)) + .until(() -> chatRoomRepositoryForTest + .findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()) + .isEmpty()); + Optional afterChatRoom = chatRoomRepositoryForTest.findOneOnOneChatRoomByParticipants(mentorUser1.getId(), menteeUser.getId()); assertThat(afterChatRoom).isEmpty(); + } @Test