-
Notifications
You must be signed in to change notification settings - Fork 2
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
[BE] feat: 하이라이트 추가 및 수정 API 구현 #813
Changes from 14 commits
c62884c
5979829
fa5aa38
b55df2f
cbbc950
84898cf
2b74e5e
eb1459e
f4418cc
921cc6e
b3a58c3
a88d090
b8ce456
ad59c37
f87efad
d3abfd3
95cf051
bb9ebb1
c700e45
834d900
16f5d34
f71d9de
4b28bd4
cd6a16c
fbd8fc4
1ce93e6
ba72762
1c16507
a7f25b8
52c350b
7e546aa
55895db
aaf1c6c
560faec
a3a968f
c226e21
132ff57
a9ceb36
24b706b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ public class HighlightController { | |
@PostMapping("/v2/highlight") | ||
public ResponseEntity<Void> highlight(@Valid @RequestBody HighlightsRequest request, | ||
@SessionAttribute("reviewRequestCode") String reviewRequestCode) { | ||
highlightService.highlight(request); | ||
highlightService.highlight(request, reviewRequestCode); | ||
return ResponseEntity.ok().build(); | ||
Comment on lines
+24
to
25
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. 커밋 순서가,, 서비스 변경 사항은 포함돼있지 않았네요 😢 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. 아차차😂 |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package reviewme.highlight.domain; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.Table; | ||
import lombok.AccessLevel; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@Table(name = "highlight") | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@EqualsAndHashCode(of = "id") | ||
@Getter | ||
public class HighLight { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(name = "review_group_id", nullable = false) | ||
private long reviewGroupId; | ||
|
||
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. 굳이 questionId와 reviewId를 가지고 있지 않아도 되지 않을까요? 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. questionId와 reviewGroupId를 말하는 게 맞겠죠? 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.
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. 맞네요 answerId로 처리하고 review group id와 question id는 뺐어요! |
||
@Column(name = "question_id", nullable = false) | ||
private long questionId; | ||
|
||
@Column(name = "answer_id", nullable = false) | ||
private long answerId; | ||
|
||
@Column(name = "line_index", nullable = false) | ||
private long lineIndex; | ||
|
||
@Column(name = "start_index", nullable = false) | ||
private long startIndex; | ||
|
||
@Column(name = "end_index", nullable = false) | ||
private long endIndex; | ||
|
||
public HighLight(long reviewGroupId, long questionId, long answerId, | ||
long lineIndex, long startIndex, long endIndex) { | ||
this.reviewGroupId = reviewGroupId; | ||
this.questionId = questionId; | ||
this.answerId = answerId; | ||
this.lineIndex = lineIndex; | ||
this.startIndex = startIndex; | ||
this.endIndex = endIndex; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package reviewme.highlight.repository; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import reviewme.highlight.domain.HighLight; | ||
|
||
public interface HighlightRepository extends JpaRepository<HighLight, Long> { | ||
|
||
void deleteByReviewGroupIdAndQuestionId(long reviewGroupId, long questionId); | ||
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. 메서드 이름으로 생성된 쿼리는 1건당 DELETE 쿼리가 날아가는 것으로 알고 있어요.
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. 오오.. 기본 메서드는 건별로!! 반영완! |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,51 @@ | ||
package reviewme.highlight.service; | ||
|
||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import reviewme.highlight.domain.HighLight; | ||
import reviewme.highlight.repository.HighlightRepository; | ||
import reviewme.highlight.service.dto.HighlightsRequest; | ||
import reviewme.highlight.service.validator.HighlightValidator; | ||
import reviewme.review.service.exception.ReviewGroupNotFoundByReviewRequestCodeException; | ||
import reviewme.reviewgroup.repository.ReviewGroupRepository; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class HighlightService { | ||
|
||
public void highlight(HighlightsRequest request) { | ||
// TODO: implement method | ||
private final HighlightRepository highlightRepository; | ||
private final ReviewGroupRepository reviewGroupRepository; | ||
|
||
private final HighlightValidator highlightValidator; | ||
|
||
@Transactional | ||
public void highlight(HighlightsRequest request, String reviewRequestCode) { | ||
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. 메서드명 그냥 하이라이트.. 괜찮을까요? 도메인명하고도 동일한데 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. 리팩토링 pr에서 editHighlight로 변경하였습니다~ |
||
long reviewGroupId = reviewGroupRepository.findByReviewRequestCode(reviewRequestCode) | ||
.orElseThrow(() -> new ReviewGroupNotFoundByReviewRequestCodeException(reviewRequestCode)) | ||
.getId(); | ||
|
||
highlightValidator.validate(request, reviewGroupId); | ||
deleteOldHighlight(request.questionId(), reviewGroupId); | ||
saveNewHighlight(request, reviewGroupId); | ||
} | ||
|
||
private void deleteOldHighlight(long questionId, long reviewGroupId) { | ||
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. 오래된... 보단 이전 어때요? 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. beforeHighlight로 수정! |
||
highlightRepository.deleteByReviewGroupIdAndQuestionId(reviewGroupId, questionId); | ||
} | ||
|
||
private void saveNewHighlight(HighlightsRequest highlightsRequest, long reviewGroupId) { | ||
List<HighLight> highLights = highlightsRequest.highlights() | ||
.stream() | ||
.flatMap(highlightRequest -> highlightRequest.lines().stream() | ||
.flatMap(line -> line.ranges().stream() | ||
.map(range -> new HighLight( | ||
reviewGroupId, highlightsRequest.questionId(), highlightRequest.answerId(), | ||
line.index(), range.startIndex(), range.endIndex() | ||
)) | ||
)) | ||
.toList(); | ||
highlightRepository.saveAll(highLights); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package reviewme.highlight.service.exception; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import reviewme.global.exception.BadRequestException; | ||
|
||
@Slf4j | ||
public class HighlightDuplicatedException extends BadRequestException { | ||
|
||
public HighlightDuplicatedException(long answerId, long lineIndex, long startIndex, long endIndex) { | ||
super("중복된 하이라이트는 생성할 수 없어요."); | ||
log.info("Highlight is duplicated - answerId: {}, lineIndex: {}, startIndex: {}, endIndex: {}", | ||
answerId, lineIndex, startIndex, endIndex); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package reviewme.highlight.service.exception; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import reviewme.global.exception.BadRequestException; | ||
|
||
@Slf4j | ||
public class InvalidHighlightLineIndexException extends BadRequestException { | ||
|
||
public InvalidHighlightLineIndexException(long submittedLineIndex, long maxLineIndex) { | ||
super("줄 번호는 %d 이하여야해요.".formatted(maxLineIndex)); | ||
log.info("Line index is out of bound - maxIndex: {}, submittedLineIndex: {}", maxLineIndex, submittedLineIndex); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package reviewme.highlight.service.exception; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import reviewme.global.exception.BadRequestException; | ||
|
||
@Slf4j | ||
public class InvalidHighlightRangeException extends BadRequestException { | ||
|
||
public InvalidHighlightRangeException(long startIndex, long endIndex) { | ||
super("하이라이트 시작 글자 인덱스는 종료 글자 인덱스보다 작아야해요."); | ||
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.
|
||
log.info("Highlight index is out of bound - startIndex: {}, endIndex: {}", startIndex, endIndex); | ||
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.
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package reviewme.highlight.service.exception; | ||
|
||
import java.util.Collection; | ||
import lombok.extern.slf4j.Slf4j; | ||
import reviewme.global.exception.BadRequestException; | ||
|
||
@Slf4j | ||
public class SubmittedAnswerAndProvidedAnswerMismatchException extends BadRequestException { | ||
|
||
public SubmittedAnswerAndProvidedAnswerMismatchException(Collection<Long> providedAnswerIds, | ||
Collection<Long> submittedAnswerIds) { | ||
super("제출된 응답이 제공된 응답과 일치하지 않아요."); | ||
log.info("SubmittedAnswer and providedAnswer mismatch - providedAnswerIds: {}, submittedAnswerIds: {}", | ||
providedAnswerIds, submittedAnswerIds); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package reviewme.highlight.service.validator; | ||
|
||
import java.util.Objects; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class HighlightKey { | ||
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. 객체 도출 좋네요! 이거 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. 추가로 네이밍도 약간 수정하면 좋겠습니다~ 키는 너무 광범위해용 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. highlightPosition 어떤가요? (사실 아루가 제안함) 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. 반영완! |
||
|
||
private final Long answerId; | ||
private final Long lineIndex; | ||
private final Long startIndex; | ||
private final Long endIndex; | ||
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.
|
||
|
||
public HighlightKey(Long answerId, Long lineIndex, Long startIndex, Long endIndex) { | ||
this.answerId = answerId; | ||
this.lineIndex = lineIndex; | ||
this.startIndex = startIndex; | ||
this.endIndex = endIndex; | ||
} | ||
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. 애초에 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. 반영완! |
||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
HighlightKey that = (HighlightKey) o; | ||
return answerId.equals(that.answerId) && lineIndex.equals(that.lineIndex) && | ||
startIndex.equals(that.startIndex) && endIndex.equals(that.endIndex); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(answerId, lineIndex, startIndex, endIndex); | ||
} | ||
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.
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.
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package reviewme.highlight.service.validator; | ||
|
||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Component; | ||
import reviewme.highlight.service.dto.HighlightRequest; | ||
import reviewme.highlight.service.dto.HighlightedLineRequest; | ||
import reviewme.highlight.service.dto.HighlightsRequest; | ||
import reviewme.highlight.service.exception.HighlightDuplicatedException; | ||
import reviewme.highlight.service.exception.InvalidHighlightLineIndexException; | ||
import reviewme.highlight.service.exception.InvalidHighlightRangeException; | ||
import reviewme.highlight.service.exception.SubmittedAnswerAndProvidedAnswerMismatchException; | ||
import reviewme.question.repository.QuestionRepository; | ||
import reviewme.review.domain.TextAnswer; | ||
import reviewme.review.repository.AnswerRepository; | ||
import reviewme.review.repository.TextAnswerRepository; | ||
import reviewme.review.service.exception.AnswerNotFoundByIdException; | ||
import reviewme.review.service.exception.SubmittedQuestionAndProvidedQuestionMismatchException; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class HighlightValidator { | ||
|
||
private final AnswerRepository answerRepository; | ||
private final TextAnswerRepository textAnswerRepository; | ||
private final QuestionRepository questionRepository; | ||
|
||
public void validate(HighlightsRequest request, long reviewGroupId) { | ||
validateAnswerByReviewGroup(request, reviewGroupId); | ||
validateQuestionByReviewGroup(request, reviewGroupId); | ||
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. 요청의 뎁스 순서로 하면 validateQuestionByReviewGroup이 먼저 되어야 할 것 같아요 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. 오 맞네요 질문 먼저 검증! |
||
validateAnswerByQuestion(request); | ||
validateLineIndex(request); | ||
validateRange(request); | ||
validateDuplicate(request); | ||
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. (개인 취향일 수도 있음) 예를 들면 validateQuestionByReviewGroup validateAnswerByQuestion (이건 정말정말 개인 취향일 수 있음) validateHighlightedResourceHiarachyRelationship() 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. (아루 코멘트 차용) validateReviewGroupContainsQuestion처럼 validate + 긍정문의 검증 행위 형식으로 바꿔보았어요! |
||
} | ||
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. validateAnswerByReviewGroup, validateQuestionByReviewGroup, validateAnswerByQuestion 이 부분은 highlight가 연관된 것들을 id로 가지고 있어서 절차적으로 검증할 수 밖에 없는 부분인데요. 리뷰 그룹과 질문으로 답변을 가져오는 것으로 한번에 검증과 동시에 자원을 가져올 수 있지 않을까요? 로직과 쿼리 한 번으로 감당할 수 있을 것 같아요. 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. 리팩토링 pr에서 반영하겠습니다! |
||
|
||
private void validateAnswerByReviewGroup(HighlightsRequest request, long reviewGroupId) { | ||
Set<Long> providedAnswerIds = answerRepository.findIdsByReviewGroupId(reviewGroupId); | ||
List<Long> submittedAnswerIds = request.highlights() | ||
.stream() | ||
.map(HighlightRequest::answerId) | ||
.toList(); | ||
|
||
if (!providedAnswerIds.containsAll(submittedAnswerIds)) { | ||
throw new SubmittedAnswerAndProvidedAnswerMismatchException(providedAnswerIds, submittedAnswerIds); | ||
} | ||
} | ||
|
||
private void validateQuestionByReviewGroup(HighlightsRequest request, long reviewGroupId) { | ||
Set<Long> providedQuestionIds = questionRepository.findIdsByReviewGroupId(reviewGroupId); | ||
long submittedQuestionId = request.questionId(); | ||
|
||
if (!providedQuestionIds.contains(submittedQuestionId)) { | ||
throw new SubmittedQuestionAndProvidedQuestionMismatchException(submittedQuestionId, providedQuestionIds); | ||
} | ||
} | ||
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. questionRepository.existByIdAndReviewGroupId() 어떠신가요? 성능도 더 좋을 것 같아요! 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. 직접적으로 연관이 없는 review group을 통해 question을 가져오도록 하는 것이 너무 특정적이고 비즈니스 로직적이지 않나해서 |
||
|
||
private void validateAnswerByQuestion(HighlightsRequest request) { | ||
Set<Long> providedAnswerIds = answerRepository.findIdsByQuestionId(request.questionId()); | ||
List<Long> submittedAnswerIds = request.highlights() | ||
.stream() | ||
.map(HighlightRequest::answerId) | ||
.toList(); | ||
|
||
if (!providedAnswerIds.containsAll(submittedAnswerIds)) { | ||
throw new SubmittedAnswerAndProvidedAnswerMismatchException(providedAnswerIds, submittedAnswerIds); | ||
} | ||
} | ||
|
||
private void validateLineIndex(HighlightsRequest request) { | ||
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. 이 부분도 객체의 책임으로 할 수 있는 방법이 없을까요? (개인적으로 답변을 함께 생성자에 넘겨서 의존하지 않고 answer를 사용하게 하거나 답변에 대한 index 길이 검증 책임을 가지는 클래스가 있어도 될 것 같아요) 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. 일급 컬렉션을 통해도 좋겠네요. 절차지향을 빌렸지만, 그래도 주는 객체지향임을 명심합시다 ⛰️ 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. 저도 동의합니다~ 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. 리팩토링 pr에서 반영하겠습니다! |
||
for (HighlightRequest highlight : request.highlights()) { | ||
TextAnswer textAnswer = textAnswerRepository.findById(highlight.answerId()) | ||
.orElseThrow(() -> new AnswerNotFoundByIdException(highlight.answerId())); | ||
long maxLineIndex = textAnswer.getContent().lines().count(); | ||
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. 오 이렇게 개행이 된 라인 수를 가져올 수 있군요! 야미~ |
||
|
||
for (HighlightedLineRequest line : highlight.lines()) { | ||
long submittedLineIndex = line.index(); | ||
if (maxLineIndex < submittedLineIndex) { | ||
throw new InvalidHighlightLineIndexException(submittedLineIndex, maxLineIndex); | ||
} | ||
} | ||
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. 이 if 문 수정이 필요해보여요. 그리고 테스트 코드에서도 아래 부분 수정해주세요! long answerLineCount = textAnswer.getContent().lines().count();
HighlightedLineRequest highlightedLineRequest = new HighlightedLineRequest(answerLineCount + 1, List.of()); // ❗️이 부분을 answerLineCount로 바꿔야 경계값이 됩니다.
HighlightRequest highlightRequest = new HighlightRequest(textAnswer.getId(), List.of(highlightedLineRequest));
HighlightsRequest highlightsRequest = new HighlightsRequest(questionId, List.of(highlightRequest)); 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. 비교대상 두개 모두 index 개념이어야 쉽게 이해갈 것 같아서 providedMaxLineIndex로 해봤는데 어떤가요? 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. 음~ 좋네용 😋 |
||
} | ||
} | ||
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. 레벨1, 2에서 어떻게 리팩터링했는지 돌아보면 실마리가 보일거예요~ 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. 해볼게요! |
||
|
||
private void validateRange(HighlightsRequest request) { | ||
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. 이 검증은 객체 책임으로 가지는 것이 좋을 것 같다는 의견입니다~ (산초 말투) 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. 의견인 것입니다~ 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. 서비스적인 속성이 아니네요 반영완! |
||
request.highlights() | ||
.stream() | ||
.flatMap(highlightRequest -> highlightRequest.lines().stream() | ||
.flatMap(highlightedLineRequest -> highlightedLineRequest.ranges().stream() | ||
.filter(range -> range.startIndex() > range.endIndex()) | ||
) | ||
) | ||
.findFirst() | ||
.ifPresent(range -> { | ||
throw new InvalidHighlightRangeException(range.startIndex(), range.endIndex()); | ||
}); | ||
} | ||
|
||
private void validateDuplicate(HighlightsRequest request) { | ||
Set<HighlightKey> uniqueHighlights = new HashSet<>(); | ||
|
||
request.highlights().forEach(highlight -> | ||
highlight.lines().forEach(line -> | ||
line.ranges().forEach(range -> { | ||
HighlightKey key = new HighlightKey( | ||
highlight.answerId(), line.index(), range.startIndex(), range.endIndex() | ||
); | ||
if (!uniqueHighlights.add(key)) { | ||
throw new HighlightDuplicatedException( | ||
highlight.answerId(), line.index(), range.startIndex(), range.endIndex() | ||
); | ||
} | ||
}) | ||
) | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package reviewme.review.repository; | ||
|
||
import java.util.Set; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Query; | ||
import org.springframework.stereotype.Repository; | ||
import reviewme.review.domain.Answer; | ||
|
||
@Repository | ||
public interface AnswerRepository extends JpaRepository<Answer, Long> { | ||
|
||
@Query(value = """ | ||
select a.id from answer a | ||
join new_review r | ||
on a.review_id = r.id | ||
where r.review_group_id = :reviewGroupId | ||
""", nativeQuery = true) | ||
Set<Long> findIdsByReviewGroupId(long reviewGroupId); | ||
|
||
@Query(value = """ | ||
select a.id from answer a | ||
join question q | ||
on a.question_id = q.id | ||
where q.id = :questionId | ||
""", nativeQuery = true) | ||
Set<Long> findIdsByQuestionId(long questionId); | ||
} | ||
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. 지금 아루의 PR이 올라와 있으니 미리 JPQL로 바꾸죠! 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. 반영완! |
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.
리뷰 컨트롤러처럼 개행을 맞추면 어떨까요?