ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Boot JPA Update 방법은 다양하다?
    개념 Self Study📝/Java 2023. 4. 27. 02:32

    1.개요

    • Final Project를 진행하는 도중 C,U,D기능에서 U기능이 에러(NullPointExceptionError)가 발생하였다. 그 이유로는 게시물에 대해서 삽입해야하는 값들이 많은데 값 삽입 도중 원치 않는값들을 입력하지 않으면 자체적으로 null값으로 넘김에 따라서 에러가 발생하였다.
    • 문제 풀이 서비스를 만들었는데 문제 풀이 특성상 객관식,주관식 구분하면 조건도 달라 에러(NullPointExceptionError)가 자주발생 하여 다른 방법의 Update JPA를 모색하였다.

     

    2. Update 방법의 다양성

     

    •  Builder를 통한 Update
      • Builder패턴을 이용하여 build를 한 후 기존에 있던 엔티티를 조회한 후 조회한 Entity에 JPA의 save메서드를 이용하여 기존에 있던 정보에 DTO를 통해 주입하여 새로운 값을 덮어씌우는 방법
    public Problem updateProblem(Long problemId, Problem updatedProblemData) {
            // Find the problem using problemId
            Optional<Problem> problemOptional = problemRepository.findById(problemId);
    
            if (!problemOptional.isPresent()) {
                throw new NoSuchElementException("Problem not found");
            }
    
            Problem existingProblem = problemOptional.get();
    
            // Update existingProblem with updatedProblemData using Builder pattern
            Problem updatedProblem = Problem.builder()
                    .id(existingProblem.getId())
                    .title(updatedProblemData.getTitle())
                    .description(updatedProblemData.getDescription())
                    .build();
    
            // Save the updated problem
            return problemRepository.save(updatedProblem);
        }

    -> 해당 방법으로 save메서드를 이용할수 있다

     

    • Setter를 통한 Update
      • 위 방법과 같이 save메서드를 이용하는 Update방법으로 하나이다.
      • Setter를 사용하면 의도가 불분명하고 변경하면 안되는 중요한 값 임에도 불구하고 변경한 값으로 착각할수 있어서 안정성이 보장이 안되기도 한다고 한다.
    public Problem updateProblem(Long problemId, Problem updatedProblemData) {
            // Find the problem using problemId
            Optional<Problem> problemOptional = problemRepository.findById(problemId);
    
            if (!problemOptional.isPresent()) {
                throw new NoSuchElementException("Problem not found");
            }
    
            Problem existingProblem = problemOptional.get();
    
            // Update existingProblem with updatedProblemData using setters
            existingProblem.setTitle(updatedProblemData.getTitle());
            existingProblem.setDescription(updatedProblemData.getDescription());
    
            // Save the updated problem
            return problemRepository.save(existingProblem);
        }

     

    • DirtyChecking을 이용한 Update
      • 위 방법과 같이 기존의 Id를 조회한 후 조회한 Id에 Entity에 정의한 메서드를 서비스에서 정의한 후 DTO를 삽입하는 방식으로 사용하면 된다.
      • 해당 방법으로 save를한다면 변경이 감지되어 변경되는 값만 인식하여 값을 업데이트 해준다.

     

    1) 다음과 같이 엔티티에 메서드를 정의한 후

     public void updateProblem(ProblemUpdateRequestDto updateRequestDto) {
                this.title = updateRequestDto.getTitle();
                this.content = updateRequestDto.getContent();
                this.answer = updateRequestDto.getAnswer();
                this.level = updateRequestDto.getLevel();
                this.writer = updateRequestDto.getWriter();
                this.hashtag = updateRequestDto.getHashTag();
                this.type = updateRequestDto.getType();
        }

    2) Service에 다음과 같이 사용할수 있다.

    public ProblemUpdateResponseDto update(ProblemUpdateRequestDto updateRequestDto) {
                //수정 권한 확인
                Optional<String> problem1 = Optional.of(problemRepository.UpdateLicense(updateRequestDto.getProblemId()));
                problem1.orElseThrow(AccessException::new);
                //데이터 존재여부확인
                Problem problem = problemRepository.findById(updateRequestDto.getProblemId()).orElseThrow(NullPointerException::new);
                    problem.updateProblem(updateRequestDto);
                    problemRepository.save(problem);
                    return ProblemUpdateResponseDto.builder()
                            .code(String.valueOf(HttpStatus.OK))
                            .msg("수정이 완료되었습니다.")
                            .build();
        }


    3. 위 방법들의 차이점 

    • Setter
      • 가장 간단하고 직관적인 방법
      • 새로운 필드가 추가되거나 수정될때 마다 Setter메서드를 사용해야한다.
      • 필드가 많아지면 코드가 길어지고, 관리하기 어려워진다.
      • 객체의 불변성 유지 불가

     

    • Builder패턴
      • 엔티티 클래스를 수정하는 대신,Builder클래스를 사용하여 변경사항을 관리한다.
      • 코드가 깔끔하며, 새로운 필드가 추가되거나 수정되더라도 Builder클래스만 변경하면 된다.
      • 객체의 불변성 유지 가능

     

    • Dirty Checking을 이용한 업데이트
      • JPA의 내장 기능을 활용하는 방법이다.
      • 트랜잭션 내에서 엔티티를 조회하고 변경하면, 트랜잭션이 종료되는 시점에 변경된 엔티티가 자동으로 저장된다.
      • 변경감지를 통해 변경된 필드만 데이터베이스에 반영되므로, 성능이 향상 된다.
      • 객체의 불변성을 보장하지 않으며, 코드가 다소 불명확해질수 있다.

     

    4. 결론

    -해당 프로젝트를 경험하며 null값이 많이 들어갈 경우에는 변경감지 방법인 DirtyChecking 방법을 사용하게 되면 성능이 향상 되는것을 알게되어 개인적으로는 DirtyChecking방법을 자주 이용할거 같다.

    '개념 Self Study📝 > Java' 카테고리의 다른 글

    QueryDsl과 JPQL어떤것을 써야할까?  (0) 2023.05.01
    Exception Handler and Validate는?  (0) 2023.04.29
    QueryDsl을 살짝 뜯어보자  (0) 2023.04.28
Designed by Tistory.