-
처음으로 회원가입시 생기는 문제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