개념 Self Study📝/Java

Spring Boot JPA Update 방법은 다양하다?

코딩 욕심쟁이 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방법을 자주 이용할거 같다.