ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 처음으로 회원가입시 생기는 문제
    Project/Greendar 2023. 4. 21. 16:09

    데이터베이스의 멤버가 아무도 없는 상태에서 회원가입을 하려다 에러가 생기는 것을 찾았다.

     

    다음 에러를 만나면 데이터 베이스 부터 한번 보자,  데이터가 있는지

    javax.persistence.NoResultException: No entity found for query

     

     

    분석 : 

    기존에는 회원 가입을 할시 다음과 같은 코드를 거친다.

     

    Repo 단의 saveMember code 이다.

     

    Service layer 에서 validateDuplicateEmail 즉 이메일을 중복 처리하는 로직을 두고 saveMember 를 최대한 member 만 생성하는 함수로 변경을 해는것 좋아보인다. 에러를 잡고 테스트코드 짜고 리펙을 해주자.

     

    public Optional<Member> saveMember(String name, String password, String email, String imageUrl, String message, String token) {
            try {
                validateDuplicateEmail(email);
                Member member = Member.of(name, password, email, imageUrl, message, token);
                em.persist(member);
                return Optional.of(member);
            } catch (NoResultException e) {
                return Optional.empty();
            }
        }

    validateDuplicateEmail :  saveMember 에서 문제가 생기는 부분이다.

    private void validateDuplicateEmail(String email){
        findOneByEmail(email).ifPresent( m -> {
            throw new IllegalStateException("이미 존재하는 이메일 입니다.");
        });
    }

     

     

    Member 에서만 사용되는 것이 아닌 다른 서비스 레이어세도 호출 중인 findOnebyEmail 이다.

    public Optional<Member> findOneByEmail(String userEmail) {
        Member member = em.createQuery("select m from Member m " +
                                "where m.email = :email"
                        , Member.class)
                .setParameter("email", userEmail)
                .getSingleResult();
        return Optional.ofNullable(member);
    }

     

    위의 코드들은 유저가 아무도 없는 첫 시점에서 이메일을 확인할 사항이 없어서 에러가 난다,,

     

    이유 :

    getSingleResult()  의  경우 쿼리 결과가 없는 경우 NoResultExecption , 여러 개의 결과가 있는 경우는 NonUniqueResultException을 던진다.     즉 , 가능하면 하나이상의 결과가 보장된 상태에서 중복되는 값이 없는 경우 사용하는것이 정확하다. 

     

    하단의 코드처럼 다음 부분을 바꿔주자.

     

    getSingleResult()  ->     " .getResultList().stream().findFirst().orElse(null); "

     

    주어진 값의 첫번째 값을 반황하거나 없으면 null 을 반환한다.

     

     

    public Optional<Member> saveMember(String name, String password, String email, String imageUrl, String message, String token) {
        try {
            validateDuplicateEmail(email);
            Member member = Member.of(name, password, email, imageUrl, message, token);
            em.persist(member);
            return Optional.of(member);
        } catch (IllegalStateException e) {
            return Optional.empty();
        }
    }
    public Optional<Member> findOneByEmail(String userEmail) {
        Member member = em.createQuery("select m from Member m " +
                                "where m.email = :email"
                        , Member.class)
                .setParameter("email", userEmail)
                .getResultList()
                .stream()
                .findFirst()
                .orElse(null);
        return Optional.ofNullable(member);
    }
    private void validateDuplicateEmail(String email){
        findOneByEmail(email).ifPresent( m -> {
            throw new IllegalStateException("이미 존재하는 이메일 입니다.");
        });
    }

     

     

    요약 :   

    기술을 알고 쓰는것이 중요하다. 

    아는것이 많아야 에러를 빠르게 잡느것을 알았다.

     

    팀원이 지금의 코드를 이해를 하게 되면 다음 편에서는 data JPA 를 이용한 리펙토링 관련 포스팅을 올릴거다. 

    'Project > Greendar' 카테고리의 다른 글

    프로젝트 그린더 Data Jpa 적용 2편  (0) 2023.04.18
    프로젝트 그린더 Data Jpa 적용 1편  (0) 2023.04.18
Designed by Tistory.