-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: 메시지 서비스에서 Querydsl 로직 분리 #678
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
0f28258
refactor: Querydsl 로직을 별도 클래스로 분리
hyewoncc 9b8db30
refactor: 빌더 패턴 안 메서드 이름 개선
hyewoncc 47f431a
refactor: 메서드 명 개선 및 서비스로 비즈니스 로직 이동으로 파라미터 변경
hyewoncc 976ccd3
refactor: DTO가 레포지토리로 넘어가지 않도록 파라미터 분리
hyewoncc 9538a28
refactor: 메서드에 필요없는 static 선언 제거
hyewoncc ddb7c83
refactor: 코드리뷰 반영 | 메서드 명, 선언 순서 개선 및 메서드 추출
hyewoncc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,32 +4,18 @@ | |
import com.pickpick.channel.domain.ChannelSubscriptionRepository; | ||
import com.pickpick.member.domain.Member; | ||
import com.pickpick.member.domain.MemberRepository; | ||
import com.pickpick.message.domain.Message; | ||
import com.pickpick.message.domain.MessageRepository; | ||
import com.pickpick.message.domain.QBookmark; | ||
import com.pickpick.message.domain.QMessage; | ||
import com.pickpick.message.domain.QReminder; | ||
import com.pickpick.message.domain.QMessageRepository; | ||
import com.pickpick.message.support.SlackIdExtractor; | ||
import com.pickpick.message.ui.dto.MessageRequest; | ||
import com.pickpick.message.ui.dto.MessageResponse; | ||
import com.pickpick.message.ui.dto.MessageResponses; | ||
import com.querydsl.core.types.ConstructorExpression; | ||
import com.querydsl.core.types.OrderSpecifier; | ||
import com.querydsl.core.types.Predicate; | ||
import com.querydsl.core.types.Projections; | ||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import java.time.Clock; | ||
import java.time.LocalDateTime; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.util.StringUtils; | ||
|
||
@Transactional(readOnly = true) | ||
@Service | ||
|
@@ -40,21 +26,17 @@ public class MessageService { | |
private static final String MENTION_MARK = "@"; | ||
|
||
private final MemberRepository members; | ||
private final MessageRepository messages; | ||
private final ChannelSubscriptionRepository channelSubscriptions; | ||
private final JPAQueryFactory jpaQueryFactory; | ||
private final Clock clock; | ||
private final QMessageRepository messages; | ||
private final SlackIdExtractor slackIdExtractor; | ||
|
||
public MessageService(final MemberRepository members, final MessageRepository messages, | ||
public MessageService(final MemberRepository members, | ||
final ChannelSubscriptionRepository channelSubscriptions, | ||
final JPAQueryFactory jpaQueryFactory, final Clock clock, | ||
final QMessageRepository messages, | ||
final SlackIdExtractor slackIdExtractor) { | ||
this.members = members; | ||
this.messages = messages; | ||
this.channelSubscriptions = channelSubscriptions; | ||
this.jpaQueryFactory = jpaQueryFactory; | ||
this.clock = clock; | ||
this.slackIdExtractor = slackIdExtractor; | ||
} | ||
|
||
|
@@ -71,7 +53,7 @@ public MessageResponses find(final Long memberId, final MessageRequest messageRe | |
private List<Long> findChannelId(final Long memberId, final MessageRequest messageRequest) { | ||
List<Long> channelIds = messageRequest.getChannelIds(); | ||
|
||
if (isNonNullNorEmpty(channelIds)) { | ||
if (isNonNullAndNotEmpty(channelIds)) { | ||
return channelIds; | ||
} | ||
|
||
|
@@ -80,27 +62,22 @@ private List<Long> findChannelId(final Long memberId, final MessageRequest messa | |
return List.of(firstSubscription.getChannelId()); | ||
} | ||
|
||
private static boolean isNonNullNorEmpty(final List<Long> channelIds) { | ||
return Objects.nonNull(channelIds) && !channelIds.isEmpty(); | ||
private boolean isNonNullAndNotEmpty(final List<Long> channelIds) { | ||
return channelIds != null && !channelIds.isEmpty(); | ||
} | ||
|
||
private List<MessageResponse> findMessages(final Long memberId, final List<Long> channelIds, | ||
final MessageRequest messageRequest) { | ||
boolean needPastMessage = messageRequest.isNeedPastMessage(); | ||
int messageCount = messageRequest.getMessageCount(); | ||
|
||
List<MessageResponse> messageResponses = jpaQueryFactory | ||
.select(getMessageResponseConstructor()) | ||
.from(QMessage.message) | ||
.leftJoin(QMessage.message.member) | ||
.leftJoin(QBookmark.bookmark) | ||
.on(existsBookmark(memberId)) | ||
.leftJoin(QReminder.reminder) | ||
.on(remainReminder(memberId)) | ||
.where(meetAllConditions(channelIds, messageRequest)) | ||
.orderBy(arrangeDateByNeedPastMessage(needPastMessage)) | ||
.limit(messageCount) | ||
.fetch(); | ||
List<MessageResponse> messageResponses = messages.findMessages( | ||
memberId, | ||
channelIds, | ||
messageRequest.getKeyword(), | ||
messageRequest.getMessageId(), | ||
messageRequest.getDate(), | ||
messageRequest.isNeedPastMessage(), | ||
messageRequest.getMessageCount()); | ||
Comment on lines
+73
to
+80
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
replaceMentionMembers(memberId, messageResponses); | ||
|
||
|
@@ -136,113 +113,14 @@ private String replaceMentionMemberInText(String text, final Map<String, String> | |
return text; | ||
} | ||
|
||
private ConstructorExpression<MessageResponse> getMessageResponseConstructor() { | ||
return Projections.constructor(MessageResponse.class, | ||
QMessage.message.id, | ||
QMessage.message.member.id, | ||
QMessage.message.member.username, | ||
QMessage.message.member.thumbnailUrl, | ||
QMessage.message.text, | ||
QMessage.message.postedDate, | ||
QMessage.message.modifiedDate, | ||
QBookmark.bookmark.id, | ||
QReminder.reminder.id, | ||
QReminder.reminder.remindDate); | ||
} | ||
|
||
private BooleanExpression existsBookmark(final Long memberId) { | ||
return QBookmark.bookmark.member.id.eq(memberId) | ||
.and(QBookmark.bookmark.message.id.eq(QMessage.message.id)); | ||
} | ||
|
||
private BooleanExpression remainReminder(final Long memberId) { | ||
return QReminder.reminder.member.id.eq(memberId) | ||
.and(QReminder.reminder.message.id.eq(QMessage.message.id)) | ||
.and(QReminder.reminder.remindDate.after(LocalDateTime.now(clock))); | ||
} | ||
|
||
private BooleanExpression meetAllConditions(final List<Long> channelIds, final MessageRequest request) { | ||
return channelIdsIn(channelIds) | ||
.and(textContains(request.getKeyword())) | ||
.and(messageHasText()) | ||
.and(decideMessageIdOrDate(request.getMessageId(), request.getDate(), request.isNeedPastMessage())); | ||
} | ||
|
||
private BooleanExpression channelIdsIn(final List<Long> channelIds) { | ||
return QMessage.message.channel.id.in(channelIds); | ||
} | ||
|
||
private BooleanExpression textContains(final String keyword) { | ||
if (StringUtils.hasText(keyword)) { | ||
return QMessage.message.text.containsIgnoreCase(keyword); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
private Predicate decideMessageIdOrDate(final Long messageId, | ||
final LocalDateTime date, | ||
final boolean needPastMessage) { | ||
if (Objects.nonNull(messageId)) { | ||
return messageIdCondition(messageId, needPastMessage); | ||
} | ||
|
||
return dateCondition(date, needPastMessage); | ||
} | ||
|
||
private BooleanExpression messageHasText() { | ||
return QMessage.message.text.isNotNull() | ||
.and(QMessage.message.text.isNotEmpty()); | ||
} | ||
|
||
|
||
private Predicate messageIdCondition(final Long messageId, final boolean needPastMessage) { | ||
Message message = messages.getById(messageId); | ||
|
||
LocalDateTime messageDate = message.getPostedDate(); | ||
|
||
if (needPastMessage) { | ||
return QMessage.message.postedDate.before(messageDate); | ||
} | ||
|
||
return QMessage.message.postedDate.after(messageDate); | ||
} | ||
|
||
private Predicate dateCondition(final LocalDateTime date, final boolean needPastMessage) { | ||
if (Objects.isNull(date)) { | ||
return null; | ||
} | ||
|
||
if (needPastMessage) { | ||
return QMessage.message.postedDate.eq(date) | ||
.or(QMessage.message.postedDate.before(date)); | ||
} | ||
|
||
return QMessage.message.postedDate.eq(date) | ||
.or(QMessage.message.postedDate.after(date)); | ||
} | ||
|
||
private OrderSpecifier<LocalDateTime> arrangeDateByNeedPastMessage(final boolean needPastMessage) { | ||
if (needPastMessage) { | ||
return QMessage.message.postedDate.desc(); | ||
} | ||
|
||
return QMessage.message.postedDate.asc(); | ||
} | ||
|
||
private boolean hasPast(final List<Long> channelIds, final MessageRequest messageRequest, | ||
final List<MessageResponse> messages) { | ||
if (messages.isEmpty()) { | ||
return false; | ||
} | ||
|
||
Integer result = jpaQueryFactory | ||
.selectOne() | ||
.from(QMessage.message) | ||
.where(meetAllHasPastCondition(channelIds, messageRequest, messages)) | ||
.fetchFirst(); | ||
|
||
return result != null; | ||
MessageResponse message = messages.get(messages.size() - 1); | ||
return this.messages.existsByChannelsBeforePostedDate(channelIds, messageRequest, message); | ||
} | ||
|
||
private boolean hasFuture(final List<Long> channelIds, final MessageRequest messageRequest, | ||
|
@@ -251,30 +129,7 @@ private boolean hasFuture(final List<Long> channelIds, final MessageRequest mess | |
return false; | ||
} | ||
|
||
Integer result = jpaQueryFactory | ||
.selectOne() | ||
.from(QMessage.message) | ||
.where(meetAllHasFutureCondition(channelIds, messageRequest, messages)) | ||
.fetchFirst(); | ||
|
||
return result != null; | ||
} | ||
|
||
private BooleanExpression meetAllHasPastCondition(final List<Long> channelIds, final MessageRequest request, | ||
final List<MessageResponse> messages) { | ||
MessageResponse targetMessage = messages.get(messages.size() - 1); | ||
|
||
return channelIdsIn(channelIds) | ||
.and(textContains(request.getKeyword())) | ||
.and(QMessage.message.postedDate.before(targetMessage.getPostedDate())); | ||
} | ||
|
||
private BooleanExpression meetAllHasFutureCondition(final List<Long> channelIds, final MessageRequest request, | ||
final List<MessageResponse> messages) { | ||
MessageResponse targetMessage = messages.get(0); | ||
|
||
return channelIdsIn(channelIds) | ||
.and(textContains(request.getKeyword())) | ||
.and(QMessage.message.postedDate.after(targetMessage.getPostedDate())); | ||
MessageResponse message = messages.get(0); | ||
return this.messages.existsByChannelsAfterPostedDate(channelIds, messageRequest, message); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
꼼꼼한 개선👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!=
굿! 👍 👍 👍 ❤️근데 이거 원래 예전 메서드명부터 좀 이상했던 것 같아요
null이 아니거나 비어있음이 아니라
null이 아니거나 비어있지 않음
이어야할 것 같아서isNonNullAndNotEmpty()
가 어떨까요?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게 적는 게 확실하겠네요! 반영하겠습니다