저번에 만든 멤버 리포지토리를 가지고, 이제 새로운 기능들을 주입시켜볼 것이다.
기본적으로 메서드의 이름을 가지고 생성, 조회, 삭제를 할 수 있다.
그러면 조회하는 요소를 이름, 이메일, 닉네임중에 몇개를 골라서 수행하는, 동적 방식의 조회는 어떻게 할까?
- 이걸 JPQL(노가다)로 한번 만들어보고,
- 테스트를 수행시켜보고,
- QueryDSL을 통해 업그레이드 시켜볼 계획이다.
일단, 검색을 시켜줄 dto와 예외처리부터 만들었다.
@Data
public class SearchMemberDto {
private String username;
private String nickname;
private String email;
public SearchMemberDto(String username, String nickname, String email) {
this.username = username;
this.nickname = nickname;
this.email = email;
}
}
이중에서 만약 검색할 요소가 없다면, null로 처리해줄 것이다.
public class NeedToAddSearchConditionException extends RuntimeException{
}
@ExceptionHandler(NeedToAddSearchConditionException.class)
@ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
public Response needToAddSearchConditionException(){
return Response.failure(404, "검색 조건을 하나라도 입력해야 합니다.");
}
이렇게 검색 조건이 없음을 예외처리시켰다.
이렇게 하나의 인터페이스와, 하나의 클래스를 만들었다.
리포지토리를 커스텀해서 만들기 위해선,
이런식으로 리포지토리에 extends시긴 인터페이스에
기능을 만들어주고,
이런식으로 Override해주어야 한다.
EntityManager를 이렇게 인스턴스로 두는 이유는, 쿼리문을 보내주는 역할을 하기 때문에 가져왔다.
SpringBoot에서 EntityManager를 가져와 자동으로 클래스를 생성해줄 것이다.
기능을 전체적으로 보여주자면,
@Override
public List<Member> search(SearchMemberDto searchMemberDto) {
StringBuilder query = new StringBuilder("select m from Member m ");
if(searchMemberDto.getUsername() == null && searchMemberDto.getNickname() == null && searchMemberDto.getEmail() == null)
throw new NeedToAddSearchConditionException();
if(searchMemberDto.getUsername() == null && searchMemberDto.getNickname() == null)
return em.createQuery("select m from Member m where m.email = :email", Member.class)
.setParameter("email", searchMemberDto.getEmail()).getResultList();
if(searchMemberDto.getNickname() == null && searchMemberDto.getEmail() == null)
return em.createQuery("select m from Member m where m.username = :username", Member.class)
.setParameter("username", searchMemberDto.getUsername()).getResultList();
if(searchMemberDto.getUsername() == null && searchMemberDto.getEmail() == null)
return em.createQuery("select m from Member m where m.nickname = :nickname", Member.class)
.setParameter("nickname", searchMemberDto.getNickname()).getResultList();
if(searchMemberDto.getUsername() == null)
return em.createQuery("select m from Member m where m.nickname = :nickname and m.email = :email", Member.class)
.setParameter("nickname", searchMemberDto.getNickname())
.setParameter("email", searchMemberDto.getEmail())
.getResultList();
if(searchMemberDto.getNickname() == null)
return em.createQuery("select m from Member m where m.username = :username and m.email = :email", Member.class)
.setParameter("username", searchMemberDto.getUsername())
.setParameter("email", searchMemberDto.getEmail())
.getResultList();
if(searchMemberDto.getEmail() == null)
return em.createQuery("select m from Member m where m.username = :username and m.nickname = :nickname", Member.class)
.setParameter("username", searchMemberDto.getUsername())
.setParameter("nickname", searchMemberDto.getNickname())
.getResultList();
return em.createQuery("select m from Member m where m.username = :username " +
"and m.nickname = :nickname " +
"and m.email = :email", Member.class)
.setParameter("username", searchMemberDto.getUsername())
.setParameter("nickname", searchMemberDto.getNickname())
.setParameter("email", searchMemberDto.getEmail())
.getResultList();
}
이런식으로 노가다를 했다.
사실 복붙을 했다.
이렇게 한 이유는, 나중에 Querydsl을 이용해 더 깔끔하게 바꿀 수 있기 때문이다.
간단하게 기능을 설명하자면, null값을 제외하고 쿼리문을 만들어, 파라미터 설정을 해주고, 결과를 List<Member>로 반환해주는 것이다.
모르겠다면 이걸 보고 오자. 쿼리 만드는 방식
이제 이걸 테스트해보았다. 하나만 예시로 보여주자면,
private void createDatas() {
for(int index = 0; index < 10; index++){
RegisterRequestDto registerRequestDto = RegisterRequestDto.builder()
.username("testUser" + index)
.nickname("test" + index)
.email("test" + index + "@test.com")
.password("password" + index)
.passwordCheck("password" + index)
.build();
Member member = new Member(registerRequestDto);
memberRepository.save(member);
em.flush();
em.clear();
}
}
@Test
@DisplayName("닉네임으로만 검색했을 때 검색한 멤버의 아이디가 같은 번호로 나온다. ")
public void searchByNickname() throws Exception{
//given
createDatas();
SearchMemberDto searchMemberDto = new SearchMemberDto(null, "test3", null);
//when
List<Member> search = memberRepository.search(searchMemberDto);
//then
assertThat(search.get(0).getUsername()).isEqualTo("testUser3");
}
위의 메서드를 통해 10개정도 데이터를 만들어두고,
아래의 메서드로 검색한 결과를 다른 인자값과 비교했다.
모든 테스트는 정상적으로 동작했다.
이제 이걸 더 깔끔하고, 재사용가능하며, 보기 좋게 만들어보자.
다음편에선 Querydsl을 추가하고, 그 다음에 Querydsl로 프로젝트를 수정해봐야겠다.
'스프링 공부 > 게시판 프로젝트 만들기' 카테고리의 다른 글
[스프링] 20. QueryDsl을 이용해 MemberCustomRepository를 더 깨끗하게!!! (0) | 2023.02.05 |
---|---|
[스프링] 19. QueryDsl 넣어주기 (0) | 2023.02.05 |
[스프링] 17. MemberRepository 테스트해보기 (0) | 2023.02.02 |
[스프링] 16. MemberRepository 만들기 (0) | 2023.02.02 |
[스프링] 15. Member 테스트대로 코드 짜보기 (0) | 2023.01.17 |