상세 컨텐츠

본문 제목

[QueryDSL] 동적쿼리로 사용자 조회하기

JAVA/SPRING

by ranlan 2021. 5. 18. 20:08

본문

728x90

관리자 계정으로 로그인했을 때 사용자 및 게시물 관리하는 ADMIN 페이지를 만들고 있다.

WHERE절 없이 사용자 전체 조회하는 로직과 관리자, 일반 회원 등 권한에 따라 사용자를 조회하는 로직을 따로 작성해도 되지만

강의에서 배운 동적쿼리를 써서 한번에 구현해보기로 하였다.

 

 

[참고] 2021.05.17 - [web/queryDSL] - [QueryDSL] 동적쿼리

 

[QueryDSL] 동적쿼리

String usernameParam = "member1"; Integer ageParam = 10; List result = searchMember(usernameParam, ageParam); 1. BooleanBuilder private List searchMember(String usernameCond, Integer ageCond) { Boo..

juran-devblog.tistory.com

 

 

엔티티와 DTO

Member

@Column
@Enumerated(EnumType.STRING)
private Role memberRole;

Role

public enum Role {
    ROLE_MEMBER, # 일반 사용자
    ROLE_ADMIN # 관리자
}

MemberDto

@Data
@NoArgsConstructor
public class MemberDto {
    private long memberNo;
    private String memberId;
    private String memberName;
    private String regDate;
    private String memberRole;

    public MemberDto(long memberNo, String memberId, String memberName, String regDate, String memberRole) {
        this.memberNo = memberNo;
        this.memberId = memberId;
        this.memberName = memberName;
        this.regDate = regDate;
        this.memberRole = memberRole;
    }

    @Builder
    public MemberDto(Member member) {
        this.memberNo = member.getMemberNo();
        this.memberId = member.getMemberId();
        this.memberName = member.getMemberNm();
        this.memberRole = member.getMemberRole().toString();
        this.regDate = member.getRegDate().toString();
    }
}

조회한 사용자 정보를 받을 DTO

조회 결과를 Member로 받아 DTO로 변환하는 경우가 많아 엔티티단에서 빌더 패턴으로 생성자 작성

 

++) 추가

생성자와 빌더를 아무생각없이 막 썼는데 이때까지만해도 빌더에 대한 이해가 부족했던듯하다,, 후에는 그냥 객체 생성시 빌더패턴으로 통일시킴!

 

 

레퍼지토리 작성

MemberRepositoryCustom

List<MemberDto> findAllByMemberRole(String memberRole);

MemberRepositoryImpl

@RequiredArgsConstructor
public class MemberRepositoryImpl implements MemberRepositoryCustom{

    private final JPAQueryFactory queryFactory;

    @Override
    public List<MemberDto> findAllByMemberRole(String memberRole) {
        List<Member> members = queryFactory
                .select(member)
                .from(member)
                .where(roleNameEq(memberRole))
                .fetch();

        return members.stream().map(m -> new MemberDto(m)).collect(Collectors.toList());
    }

    private BooleanExpression roleNameEq(String role) {
        return role != null ? member.memberRole.eq(Role.valueOf(role)) : null;
    }
}

원래는 memberRole의 null 체크할 때 springframework.util.StringUtils의 hasText()를 쓰고 싶었는데 이상하게 StringUtils가 import가 안된다 ㅠㅠ

일단은 서비스 계층에서 먼저 확인하기 때문에 null인지만 확인을 하였다.

 

 

서비스

MemberService

@Transactional
public List<MemberDto> findMemberAllByRole(String role) {
    return memberRepository.findAllByMemberRole(toRole(role));
}

private String toRole(String role) {
    switch (role) {
        case "admin":
            return Role.ROLE_ADMIN.toString();
        case "member":
            return Role.ROLE_MEMBER.toString();
        default:
            return null;
    }
}

ajax 호출할 때 보내는 파리미터와 DB에 저장된 권한명이 같지 않기도 하고 예외 처리를 위해 switch 문으로 권한별로 Role의 권한명을을 반환하도록 하였다.

레퍼지토리에서 String 타입으로 권한명을 비교하기 때문에 권한을 Enum 타입으로 바꿨다가 다시 toString()을 썼다가 그렇게 하고 있다.

조금 지저분한것 같기도 하고... Enum 타입은 비교를 어떻게 해야하는지 더 공부해야겠다.

 

또 하나! 메서드명의 통일이 필요한 듯 🧐

 

 

API 컨트롤러

BoardApiController

@GetMapping("/list")
public ResponseEntity<?> findMemberByRole(@RequestParam(value = "role", required = false) String role) {
    ApiResponse apiResponse = new ApiResponse(true, "사용자 권한별 조회 - " + role);
    apiResponse.putData("memberList", memberService.findMemberByRole(role));

    return ResponseEntity.ok(apiResponse);
}

 

 

프론트 JS

$.ajax({
    url: baseUrl + '/api/member/list',
    type: 'GET',
    contentType: 'application/json',
    data: {
        // query param
        role: role
    },
    beforeSend: function (xhr) {
        // spring security header
        xhr.setRequestHeader("${_csrf.headerName}", "${_csrf.token}");
    },
    success: function (result) {
        // ajax 성공시 처리할 부분
        });
    }, error: function (error) {
        console.log('error')
    }
});

 

 

결과

전체 조회하는 경우(권한명이 null인 경우)

>> http://localhost:9090/api/member/list?role=

select
        member0_.member_no as member_n1_3_,
        member0_.reg_date as reg_date2_3_,
        member0_.update_date as update_d3_3_,
        member0_.member_email as member_e4_3_,
        member0_.member_id as member_i5_3_,
        member0_.member_nm as member_n6_3_,
        member0_.member_pw as member_p7_3_,
        member0_.member_role as member_r8_3_,
        member0_.member_tell as member_t9_3_,
        member0_.member_yn as member_10_3_ 
    from
        member member0_

 

권한별로 조회하는 경우(권한명이 주어진 경우)

>> http://localhost:9090/api/member/list?role=member

select
        member0_.member_no as member_n1_3_,
        member0_.reg_date as reg_date2_3_,
        member0_.update_date as update_d3_3_,
        member0_.member_email as member_e4_3_,
        member0_.member_id as member_i5_3_,
        member0_.member_nm as member_n6_3_,
        member0_.member_pw as member_p7_3_,
        member0_.member_role as member_r8_3_,
        member0_.member_tell as member_t9_3_,
        member0_.member_yn as member_10_3_ 
    from
        member member0_ 
    where
        member0_.member_role=?

 

이렇게 null일때는 where 조건이 생략되고 파라미터가 있을 경우 where 절이 생기는 것을 확인할 수 있다.

 

 

728x90

관련글 더보기

댓글 영역