인프런 커뮤니티 질문&답변

최용호님의 프로필 이미지
최용호

작성한 질문수

실전! Querydsl

시작 - JPQL vs Querydsl

QueryDsl 메소드에 대한 질문있습니다.

작성

·

429

0

이해를 돕기위해 코드 첨삭합니다.

대략적인 코드의 내용은

유저가 시험을 풀고 유저가 푼 문제를 긁어와서 그 문제들의 한 필드(Temporary) 업데이트 즉,

 제출한 시험문제 전체를 업데이트하는 그런코드입니다. 

 

Service ------------------------------------------------------------------------------------------

    @Transactional
    @Override
    public ExamMultiSubjectUpdateResponseDto updateExamTemporary(Long courseUserSeq,Long examSeq) {

        CourseUser courseUser = courseUserRepository.findById(courseUserSeq)
                .orElseThrow(() -> new RestException(HttpStatus.NOT_FOUND, "찾을 수 없는 유저-과정 입니다. courseUserSeq = " + courseUserSeq));
        Exam exam = examRepository.findBySeq(examSeq)
                .orElseThrow(() -> new RestException(HttpStatus.NOT_FOUND, "일치하는 시험을 찾을 수 없습니다. examSeq=" + examSeq));

        //유저가 시험보기를 누른 첫 스타트 시작시간 가져오기
        // (객관식 개수가 0 일수도 있고 주관식개수가 0 일수도 있기때문에 2개의 메소드진행)
        timeCheckMultiple(courseUserSeq, exam);
        timeCheckSubjective(courseUserSeq, exam);

        //유저-과정에 등록된 유저가 객관식, 주관식에 모든 임시데이터를 가져온다.
        String tYn = "Y";
        List<ExamMultipleChoiceResult> multiEntityList = examMultipleChoiceResultRepository.findAllByCourseUserSeqAndTemporaryYn(courseUserSeq,tYn);
        List<ExamSubjectiveResult> subjectEntityList = examSubjectiveResultRepository.findAllByCourseUserSeqAndTemporaryYn(courseUserSeq,tYn);

        //시험 테이블에 등록된 주관식 객관식 개수
        Integer objCnt = exam.getObjCnt();
        Integer subCnt = exam.getSubCnt();

        log.info("해당과정을 듣는 유저가 입력한 객관식 = {}  ::  해당과정을 듣는 유저가 입력한 등록한 주관식 = {}",multiEntityList.size(),subjectEntityList.size());
        // 시험 테이블에 등록된 개수들과 유저가 입력한 개수의 조건 비교
        if (multiEntityList.size() + subjectEntityList.size() == objCnt+subCnt){
            ExamMultiSubjectUpdateResponseDto examMultiSubjectUpdateResponseDto = examRepository.updateTemporary(multiEntityList, subjectEntityList,courseUser);
            return examMultiSubjectUpdateResponseDto;
        } else if (!(multiEntityList.size() + subjectEntityList.size() > 0)){
            throw new RestException(HttpStatus.BAD_REQUEST,"제출해야 할 주관식,객관식 데이터가 없습니다.");
        } else {
            throw new RestException(HttpStatus.BAD_REQUEST,"모든 객관식, 주관식에 답을 입력해주세요.");
        }
    }

QueryDsl ----------------------------------------------------------------------------------------

 

  @Override
public ExamMultiSubjectUpdateResponseDto updateTemporary(List<ExamMultipleChoiceResult> multiEntityList, List<ExamSubjectiveResult> subjectEntityList, CourseUser courseUser) { //유저가 체크한 문제를 임시 상태(temporaryYn)에서 제출상태로 변경 Y 면 임시 저장상태 N 이면 제출한상태 long multi = queryFactory .update(qExamMultipleChoiceResult) .set(qExamMultipleChoiceResult.temporaryYn, "N") .where(qExamMultipleChoiceResult.in(multiEntityList)) .execute(); long subject = queryFactory .update(qExamSubjectiveResult) .set(qExamSubjectiveResult.temporaryYn, "N") .where(qExamSubjectiveResult.in(subjectEntityList)) .execute(); em.flush(); em.clear(); if (multi == 0 || subject == 0){ throw new RestException(HttpStatus.BAD_REQUEST,"시험 제출에 실패하였습니다."); } //Ip주소가 프록시나 로드밸런서를 통해 호출되는 경우 로드밸런서의 IP가 나온다 //이 경우를 방지하기 위해 X-Forwarded-For 값을 확인하고 없을 경우 getRemoteAddr()을 사용한다. HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest(); String ip = ClientsUtils.getRemoteIP(req); //유저 시험 채점 테이블 기본값 세팅 (유저가 시험 제출을하면 관리자가 어떤유저가 제출한건지 알기위함.) //유저가 이미 제출했던 시험이 있는지 검증 if (!examUserRepository.existsByCourseUserSeq(courseUser.getSeq())){ examUserRepository.save(new ExamUser(courseUser,0.0,null,"Y","N",null, LocalDateTime.now(),null,ip,null)); } else { throw new RestException(HttpStatus.NOT_FOUND,"이미 제출하셨던 시험이 있습니다."); } //위 em.flush(),em.clear() 로 인해 //ExamMultiSubjectUpdateResponseDto 에 업데이트한 쿼리가 담기지않아 새로 호출 List<ExamMultipleChoiceResult> reFindMulti = examMultipleChoiceResultRepository.findAllByCourseUserSeq(courseUser.getSeq()); List<ExamSubjectiveResult> reFindSubject = examSubjectiveResultRepository.findAllByCourseUserSeq(courseUser.getSeq()); return ExamMultiSubjectUpdateResponseDto.builder() .multiEntityList(reFindMulti) .subjectEntityList(reFindSubject) .build(); }

 

위 코드에서 제가 궁금한 점은 

1. QueryDsl 메소드안에서 위처럼 examUserRepository(DI :: 의존성주입)를 써도되는지..혹은 서비스단에서 처리하는게 맞는지..

2. 위 코드에서 지양해야 하는점이있는지..

피드백주시면 감사하겠습니다..

답변 1

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 최용호님^^

updateTemporary()는 서비스 계층으로 올리는 것이 더 좋을 것 같아요. 그리고 querydsl을 사용하는 부분들을 리포지토리로 보내구요.

죄송하지만 앞으로는 질문 안내에 있는 것 처럼, 학습 관련된 질문을 올려주시길 부탁드립니다. 저도 마음으로는 도움을 드리고 싶지만, 하루에도 수 많은 분들이 질문을 올려주십니다. 그래서 강의 학습과 관련된 질문에 초점을 맞추는 것이 맞다 생각합니다. 다시한번 이해를 부탁드립니다.

감사합니다.

최용호님의 프로필 이미지
최용호
질문자

네 감사합니다.^^

최용호님의 프로필 이미지
최용호

작성한 질문수

질문하기