본문 바로가기
Java & Spring Boot

Querydsl OneToMany 조건 검색, ListPath

by 향각산 2021. 10. 20.

내가 원했던 것은 다음과 같다. 1:n 매핑관계를 나타내는 Entity이다. 예시라서 디테일한건 없음.

@Data
@Entity
public class User {
	private Long id;
	private String name;
	private List<Profile> profiles;
}

@Data
@Entity
public class Profile {
	private Long id;
	private User user;
	private Type type; // PUBLIC, PRIVATE,
	private String nickName;
}

DB 테스트 데이터 

// user
	{ id : 1, name : "user1" } // 조회할 데이터
	{ id : 2, name : "user2" } 
	

// profile
	{ id : 1, userId : 1, type : PUBLIC,   nickName : "test1" }
	{ id : 2, userId : 1, type : PUBLIC,   nickName : "test2" }
	{ id : 3, userId : 1, type : PRIVATE, nickName : "test2" } // 일치하는 데이터
	{ id : 4, userId : 2, type : PUBLIC,   nickName : "test1" }
	{ id : 5, userId : 2, type : PUBLIC,   nickName : "test2" }
	{ id : 6, userId : 2, type : PRIVATE, nickName : "test3" }

 

요구사항 

  • 전체 User의 Profile 중 type == PRIVATE && nickName == test2 인 유저 조회
  • 조회하는 데이터는 형식 : [{ "test2" }]
public class SearchCondition {
	private List<Long> userIds;
	private List<String> nickNames;
}

// Querydsl
public List<User> findUserByCondition(SearchCondition condition) {

	QUser $user = QUser.uesr;
	QProfile $profile = QProfile.profile;
    
	BooleanBuilder builder = new BooleanBuilder;
    
	if (Objects.nonNull(condition.getNickNames()) && !condition.getNickNames().isEmpty()) {
			builder.and(JPAExpressions.selectOne()
			.from($profile)
			.where($profile.user.eq($user)),
			$profile.type.eq(TYPE.PRIVATE),
			$profile.nickName.in(condition.getNickNames()
			))
			.exists());
	}
}

위와 같이 처리해야 한다. user의 profile list를 바로 가져올수 있지만 해당 조건을 처리할 방법이 없다.

왜냐면 해당 문제는 조건이 두 개가 존재하기 때문이다.

 

만약 조건이 type == PRIVATE && nickName == test2 가 아니라, 

type == PRIVATE || nickName == test2 라면 해결이 가능하다. 하지만 and 조건이기 때문에 불가능.

처음에는 다음과 같이 작성했었다.

builder(user.profile.any().type.eq(Type.PRIVATE).and(user.profile.any().nickName.in(condition.getNickNames())));

다음과 같이 작성하면 실제 sql 쿼리가 두개의 조건이 or로 나간다.

 

1. profile 리스트에 PRIVATE가 있어서 통과 

2. profile 리스트에 nickName이 일치하는게 있어서 통과

 

위 형태로 어떻게든 처리하려고 해봤지만 방법을 못찾았다. 혹시라도 있으면 알려주시길.