- 쿼리 한번으로 대량 데이터 수정
- 수정, 삭제의 벌크 연산의 경우 영속성 컨텍스트를 통하는 것이 아닌 DB에 직접 쿼리를 날리는 것이기 때문에, 영속성 컨텍스트의 데이터와 불일치하는 상황이 발생한다.
- 영속성 컨텍스트와 DB의 데이터를 일치시켜주지 않을 경우 데이터 일치성에 있어서 큰 문제가 발생 할 수 있다.
@Test
public void bulkUpdate() {
queryFactory
.update(member)
.set(member.username, "비회원")
.where(member.age.lt(28))
.execute();
- 위와 같이 코드를 작성하여 실행하게 되면 where문의 조건에 맞게 DB의 데이터들은 변경되지만 영속성 컨텍스트의 값은 해당 조건과 무관하게 변경되지 않는다.
- JPA는 select이 호출되면 DB에서 값을 가져와도 영속성 컨텍스트에 값이 있으면 DB에서 가져온 값을 버리고 영속성 컨텍스트에 있는 값을 사용한다. 즉, 영속성 컨텍스트가 항상 우선권을 가진다.
em.flush();
em.clear();
List<Member> result = queryFactory
.selectFrom(member)
.fetch();
for (Member member1 : result) {
System.out.println("member1 = " + member1);
}
}
- 때문에 위와 같이 flush()와 clear() 메서드를 사용하여 영속성 컨텍스를 비워주고 select 쿼리 호출 시 새롭게 DB에서 데이터를 가져와 영속성 컨텍스트를 채워넣어 줘야 데이터의 일치가 보장된다.
1. flush(), clear()를 해주지 않은 경우
- 위 결과와 같이 DB에는 데이터가 변경되었지만 select를 통해 member 엔티티를 조회하게 되면 변경되지 않은 값이 출력되는 것을 확인 할 수 있다.
2. flush(), clear()를 메서드를 적용할 경우
- 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();
}
@Test
public void bulkDelete() {
long count = queryFactory
.delete(member)
.where(member.age.gt(18))
.execute();
}
- SQL function 호출하기
- 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);
}
}
- function 뒤으 {0}, {1}, {2} 부분에 아래 작성된 member.username, "member", "M"이 대입되어 replace가 적용되어 데이터를 변경한다.
- replace가 어떻게 사용되는지 궁금할 수 있다.
- 위와 같이 H2Dialect 클래스에 많은 SQLFunction이 정의되어 있어 가져다가 사용하면 된다.
@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);
}
}
- 모든 DB에서 사용할 수 있는 간단한 SQL 문법들은 위와 같이
.where(member.username.eq(
Expressions.stringTemplate("function('lower', {0})", member.username))
- SQLFunction을 굳이 사용하기보단
.where(member.username.eq(member.username.lower()))
- 위와 같이 JPA가 기본적으로 제공하기 때문에 사용하면 된다.
출처 : 인프런 - 김영한(실전! Querydsl)
'Programming > Querydsl' 카테고리의 다른 글
Querydsl - 순수 JPA와 Querydsl (0) | 2023.07.31 |
---|---|
Querydsl - 중급 문법 (2) 동적 쿼리 (0) | 2023.07.28 |
Querydsl - 중급 문법 (1) (프로젝션) (0) | 2023.07.28 |
Querydsl - 기본 문법 (3) (조인, 서브 쿼리, Case문, 상수, 문자 더하기) (0) | 2023.07.27 |
Querydsl - 기본 문법 (2) (결과 조회, 정렬, 페이징, 집합) (0) | 2023.07.27 |