티스토리 뷰
유저 권한에 따라 모든 쿼리에 조회조건이 추가되야 하는 경우가 생겼다.
예를 들면 '본인 소속 데이터만 조회해야 하는 권한자 일 경우'
매 쿼리마다 유저권한을 체크해서
유저 부서와 쿼리 데이터를 비교하는 조건절을 추가해야 하는 상황이 생겼다.
제네릭하게 구현해보려다가
PathBuilder 를 사용해서 모든 엔티티를 비교하는 메소드를 작성하였다.
PathBuilder 란?
QueryDSL 에서 제공하는 유연한 클래스이며,
엔티티의 QClass를 직접 사용하는 대신, 동적으로 엔티티의 속성에 접근할 수 있는 클래스이다.
동적으로 생성된 엔티티나 필드를 다룰때 유용하다.
PathBuilder 의 특징이라면
QClass 없이 엔티티에 접근가능하고
제네릭 메소드와 함께 사용하여 런타임 오류를 방지하고
특정 엔티티에 국한되지 않고 다양하게 활용 가능하다.
PathBuilder 의 기본 사용법
PathBuilder<Entity> pathBuilder = new PathBuilder<>(Entity.class, "Entity");
BooleanExpression condition = pathBuilder.getString("name").eq("Sample");
위와 같이 초기화하여 엔티티에 접근하고
필드에 동등한 데이터가 있는지 비교할 수 있다.
위의 정보를 토대로 유저의 권한과 각 메뉴들의 부서코드와 비교하기 위해 아래와 같이 공통 메소드를 하나 작성했다.
@Component
public class QueryFilter {
public <T> BooleanExpression userDeptCodeFilter(Member member, EntityPathBase<T> entity) {
PathBuilder<T> pathBuilder = new PathBuilder<>(entity.getType(), entity.getMetadata().getName());
if ((member.getType().equals("U"))) {
return pathBuilder.getString("deptCode").eq(member.getDepartment());
}
return null;
}
}
queryDSL 조건을 처리하기 위해 BooleanExpression 타입으로 결과를 리턴하고
인자로는 유저 정보와 QClass 의 모체인 EntityPathBase 타입으로 받기로 했다.
pathBuilder 를 초기화하면서 엔티티의 타입정보와 메타데이터 이름들을 가져왔고
유저의 권한에 따라 전사조회가 아닌 소속조회라면
엔티티의 부서코드를 유저 부서코드와 비교하게끔 하였다.
쿼리에서 조건절에 작성한 필터를 추가해주면
엔티티들 상관없이 동일한 로직을 수행하게끔 하였다.
private final QueryFilter queryFilter;
List<YourEntity> findSearch(...) {
return queryFactory.selectFrom(yourEntity)
.where(... 조건들 ....
, queryFilter.userDeptCodeFilter(member, yourEntity)
)
.fetch();
}
더 좋은 방법들이 있을 수 있으나
pathBuilder 를 안써봐서 한번 써보는 취지로 사용해보았다.
참고사이트
'Java > JPA, QueryDSL' 카테고리의 다른 글
[JPA] Soft Delete 사용. (feat.@SQLDelete) (0) | 2024.11.01 |
---|---|
[QueryDSL] LocalDateTime 형식 DateTimeExpression 으로 년월(YYYYMM)만 비교하기 (0) | 2024.03.07 |
[JPA] DB환경별 다중 schema, catalog 엔티티 적용법 (2) | 2023.11.22 |
[QueryDSL] Projections, @QueryProjection 을 사용하여 DTO로 반환하기 (1) | 2023.11.13 |
[QueryDSL] 다중 Datasource 설정하기 (feat.@Qualifier 사용) (0) | 2023.11.13 |