김영한님의 '실전! Querydsl'을 수강하며 정리하는 글입니다
동적 쿼리를 해결하는 두가지 방식
@Test
public void dynamicQuery_BooleanBuilder() {
String usernameParam = "member1";
Integer ageParam = 10;
List<Member> result = searchMember1(usernameParam, ageParam);
assertThat(result.size()).isEqualTo(1);
}
private List<Member> searchMember1(String usernameCond, Integer ageCond) {
BooleanBuilder builder = new BooleanBuilder();
if (usernameCond != null) {
builder.and(member.username.eq(usernameCond));
}
if (ageCond != null) {
builder.and(member.age.eq(ageCond));
}
return queryFactory
.selectFrom(member)
.where(builder)
.fetch();
}
@Test
public void dynamicQuery_WhereParam() {
String usernameParam = "member1";
Integer ageParam = 10;
List<Member> result = searchMember2(usernameParam, ageParam);
assertThat(result.size()).isEqualTo(1);
}
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
//.where(usernameEq(usernameCond), ageEq(ageCond))
.where(allEq(usernameCond, ageCond))
.fetch();
}
private BooleanExpression usernameEq(String usernameCond) {
return usernameCond != null ? member.username.eq(usernameCond) : null;
}
private BooleanExpression ageEq(Integer ageCond) {
return ageCond != null ? member.age.eq(ageCond) : null;
}
private BooleanExpression allEq(String usernameCond, Integer ageCond) {
return usernameEq(usernameCond).and(ageEq(ageCond));
}
@Test
public void bulkUpdate() {
long count = queryFactory
.update(member)
.set(member.username, "비회원")
.where(member.age.lt(28))
.execute();
em.flush();
em.clear();
List<Member> result = queryFactory
.selectFrom(member)
.fetch();
for (Member member1 : result) {
System.out.println("member1 = " + member1);
}
}
JPQL 배치와 마찬가지로, 영속성 컨텍스트에 있는 엔티티를 무시하고 바로 DB에 접근하기 때문에 영속성 컨텍스트와, 디비에 있는 데이터가 다르다는 문제가 발생한다. 그러므로 배치 쿼리를 실행하고 나면 영속성 컨텍스트를 초기화 하는 것이 안전하다.
@Test
public void bulkAdd() {
long count = queryFactory
.update(member)
//.set(member.age, member.age.add(1))
.set(member.age, member.age.multiply(2))
.execute();
}
long count = queryFactory
.delete(member)
.where(member.age.gt(18))
.execute();
SQL function은 JPA와 같이 Dialect에 등록된 내용만 호출할 수 있다.
member -> M으로 변경하는 replace 함수 사용
@Test
public void sqlFunction() {
List<String> result = queryFactory
.select(Expressions.stringTemplate("function('replace', {0}, {1}, {2})",
member.username, "member", "M"))
.from(member)
.fetch();
for (String s : result) {
System.out.println("s = " + s);
}
}
소문자로 변경해서 비교
@Test
public void sqlFunction2() {
List<String> result = queryFactory
.select(member.username)
.from(member)
// .where(member.username.eq(
// Expressions.stringTemplate("function('lower', {0})", member.username)))
.where(member.username.eq(member.username.lower()))
.fetch();
for (String s : result) {
System.out.println("s = " + s);
}
}
lower같은 자주쓰이는 함수들은 querydsl이 대부분 내장하고 있다. 따라서 주석처리와 밑에 .where(member.username.eq(member.username.lower()))
는 똑같은 코드이다.