[JPA] QueryDSL
๐ QueryDSL์ด๋?
QueryDSL
์ HQL(Hibernate Query Language)
๋ฅผ ํ์
์ ์์ ํ๊ฒ(type-safe) ์์ฑ ๋ฐ ๊ด๋ฆฌํ๋ ํ๋ ์์ํฌ์ด๋ค. ์ ์ ํ์
์ ํตํด SQL์ด๋ JPQL ์ฟผ๋ฆฌ๋ฅผ ์๋ฐ ์ฝ๋๋ก ์์ฑํ ์ ์๋ค.
์ ์ ํ์ ์ด๋ ์ปดํ์ผ ์์ ์ ๋ณ์๋ ๊ฐ์ฒด์ ๋ฐ์ดํฐ ํ์ ์ด ๋ฏธ๋ฆฌ ๊ฒฐ์ ๋๋ ๊ฒ์ ๋งํ๋ค.
โtype-safeโ๋ผ๋ ๊ฒ์ ์ปดํ์ผ๋ฌ๊ฐ ํ๋ก๊ทธ๋จ ์คํ ์ ๋ฐ์ดํฐ ํ์ ์ ํ์ธํ์ฌ ํ์ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
DSL์ Domain-Specific Language์ ์ฝ์๋ก, ํน์ ๋๋ฉ์ธ์ ์ด์ ์ ๋ง์ถ ์ํํธ์จ์ด ์ธ์ด์ด๋ค. QueryDSL์์ ๋๋ฉ์ธ์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ผ๊ณ ๋ณผ ์ ์๋ค.
๐ ๋ฑ์ฅ ๋ฐฐ๊ฒฝ
QueryDSL ์ด์ ์๋ Mybatis, JPQL, Criteria๊ณผ ๊ฐ์ด ๋ฌธ์์ด ํํ๋ก ์ฟผ๋ฆฌ๋ฌธ์ ์์ฑํ์๋ค. ๋ฐ๋ผ์ ์ปดํ์ผ ์์ ์ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๊ณ , ์ ์ง๋ณด์๊ฐ ์ด๋ ค์์ก๋ค. ๊ณต์ JPA์์ ์ ๊ณตํ๋ Criteria API๋ ์ฟผ๋ฆฌ๋ฅผ ์๋ฐ ์ฝ๋๋ก ์์ฑํ ์ ์๋๋ก ์ง์ํ์ง๋ง, ์ฝ๋๊ฐ ๋ํดํ๊ณ ์ง๊ด์ฑ์ด ๋จ์ด์ง๋ค๋ ๋จ์ ์ด ์์๋ค. ๋ํ ์ค๋ฌด์์๋ ๋ค์ํ ์กฐ๊ฑด์ ๋์ ์ฟผ๋ฆฌ์ ํ์์ฑ์ด ์ฆ๊ฐํ์๋ค. ์ด๋ฌํ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด QueryDSL์ด ๋ฑ์ฅํ์๋ค.
๐ ์ฅ์
- ๋ฌธ์์ด์ด ์๋ ์ฝ๋๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ์ฌ ์ปดํ์ผ ์์ ์ ์ค๋ฅ๋ฅผ ์ฐพ์๋ผ ์ ์๋ค.
- Q-Class, ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ณต์กํ ์ฟผ๋ฆฌ๋ ๋์ ์ฟผ๋ฆฌ ์์ฑ์ ์์ฑํ ์ ์๋ค.
- JPQL ๋ฌธ๋ฒ๊ณผ ์ ์ฌํ ํํ๋ก ์์ฑํ ์ ์๋ค.
๐ Q-Class
Q-Class
๋ QueryDSL์ด ์ ๊ณตํ๋ ๋ฉํ ๋ชจ๋ธ ํด๋์ค์ด๋ค. ์ํฐํฐ ํด๋์ค์ ๊ตฌ์กฐ์ ํ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋์ผ๋ก ์์ฑ๋๋ฉฐ, ๊ฐ ์ํฐํฐ์ ํ๋ ์ ๋ณด๋ฅผ ๋ณ์๋ก ๊ฐ์ง๋ค.
๋ฉํ ๋ชจ๋ธ ํด๋์ค๋ ํน์ ๋ชจ๋ธ์ ๊ตฌ์กฐ๋ฅผ ์ปดํ์ผ ์์ ์ ์ ์ ์ผ๋ก ํํํ๋ ํด๋์ค์ด๋ค. ์ด๋ฅผ ํตํด ํ๋๋ช ์คํ, ํ์ ๋ถ์ผ์น ๋ฑ๊ณผ ๊ฐ์ ์ค๋ฅ๋ฅผ ์คํ ์ ์ ๋ฐ๊ฒฌํ ์ ์๊ฒ ๋๋ค.
์ํฐํฐ ํด๋์ค์ @Entity
์ด๋
ธํ
์ด์
์ด ๋ถ์ด์๋ค๋ฉด Q-Class๋ ๋น๋ ์์ ์ JPAAnnotationProcessor
์ ์ํด ์๋์ผ๋ก ์์ฑ๋๋ค. Q-Class๋ ์ํฐํฐ ์ด๋ฆ ์์ โQโ๊ฐ ๋ถ์ด ์์ฑ๋๋ค. ๋ง์ฝ ์ํฐํฐ ์ด๋ฆ์ด User
๋ผ๋ฉด ํด๋น ์ํฐํฐ์ Q-Class๋ QUser
๊ฐ ๋๋ค.
JPAAnnotationProcessor๋
APT(Annotation Processing Tool)
์ด๋ค. APT๋ Java ์ปดํ์ผ๋ฌ์ ์ผ๋ถ๋ก, ์ปดํ์ผ ์์ ์ ์ด๋ ธํ ์ด์ ์ ๋ถ์ํ๊ณ ์ถ๊ฐ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋๊ตฌ์ด๋ค. ๋ค๋ฅธ ์์๋ก Lombok์@Getter
๊ฐ ์๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Entity
public class Member {
@Id
private Long id;
private String username;
private int age;
}
public class QMember extends EntityPathBase<Member> {
public static final QMember member = new QMember("member");
public final StringPath username = createString("username");
public final NumberPath<Integer> age = createNumber("age", Integer.class);
public final NumberPath<Long> id = createNumber("id", Long.class);
}
์ปดํ์ผ ์์ ์ ์์ ๊ฐ์ Q-Class๊ฐ ์์ฑ๋๋ค.
JPAQueryFactory
๋ฅผ ์ฌ์ฉํ์ฌ Q-Class ๊ธฐ๋ฐ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋น๋ ํจํด์ผ๋ก ์์ฑํ ์ ์๋ค.
1
2
3
4
5
6
7
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QMember member = QMember.member;
Member result = queryFactory
.selectFrom(member)
.where(member.username.eq("whqtker"))
.fetchOne();
1
2
3
4
5
6
7
8
@Configuration
public class QueryDSLConfig {
@Bean
JPAQueryFactory jpaQueryFactory(EntityManager em) {
return new JPAQueryFactory(em);
}
}
๐ QueryDSL ์ค์
1
2
3
4
5
// QueryDSL
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
dependencies
์ QueryDSL ์์กด์ฑ์ ์ถ๊ฐํ๋ค.
1
2
3
clean {
delete file('src/main/generated')
}
์ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ฉด gradle clean
๋ช
๋ น์ผ๋ก ์์ฑ๋ Q-Class๋ฅผ ์๋์ผ๋ก ์ญ์ ํ ์ ์๋ค.
๐ ๊ธฐ๋ณธ ๋ฌธ๋ฒ
1
2
3
4
5
6
QMember member = QMember.member;
Member result = queryFactory
.selectFrom(member)
.where(member.username.eq("member1"))
.fetchOne();
QueryDSL์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฉ์๋ ์ฒด์ด๋์ ํตํด ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ค.
selectFrom()
: ์กฐํํ ์ํฐํฐ๋ฅผ ์ง์ ํ๋ค.
where()
: ์กฐ๊ฑด์ ์ ์ถ๊ฐํ๋ค.
fetchOne()
: ๋จ์ผ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๋ค.
์กฐ๊ฑด
1
2
3
4
5
.where(
member.age.between(10, 30)
.and(member.username.like("%user%"))
)
where์ ์ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฉ์๋ ์ค ์ผ๋ถ๋ง ์ดํด๋ณด์.
eq()
: ๊ฐ์ด ๊ฐ์์ง ๋น๊ตํ๋ค.
ne()
: ๊ฐ์ด ๋ค๋ฅธ์ง ๋น๊ตํ๋ค.
goe()
: ์ด์(โฅ)
lt()
: ๋ฏธ๋ง(<)
like()
: ๋ฌธ์์ด ํจํด์ ๋งค์นญํ ๋ ์ฌ์ฉํ๋ค.
์กฐ๊ฑด์ null๋ก ์ค์ ํ๋ ๊ฒฝ์ฐ ํด๋น ์กฐ๊ฑด์ ๋ฌด์๋๋ค.
์กฐํ
1
2
3
4
QueryResults<Member> results = queryFactory
.selectFrom(member)
.fetchResults();
fetch()
: ๊ฒฐ๊ณผ ๋ฆฌ์คํธ๋ฅผ ๋ฆฌํดํ๋ค. ๋ฆฌํด ํ์
์ List<T>
์ด๋ค.
fetchOne()
: ๋จ์ผ ๊ฒฐ๊ณผ ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๋ค. ๊ฒฐ๊ณผ๊ฐ ์๋ค๋ฉด null
, ๊ฒฐ๊ณผ๊ฐ ๋ ์ด์์ด๋ผ๋ฉด NonUniqueResultException
์ ๋ฐ์์ํจ๋ค.
fetchFirst()
: ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์์ ์ฒซ ๋ฒ์งธ ๊ฒฐ๊ณผ๋ง ๋ฆฌํดํ๋ค. limit(1).fetchOne()
๊ณผ ๋์ผํ ๋์์ ์ํํ๋ค. ๊ฒฐ๊ณผ๊ฐ ์๋ค๋ฉด null
์ ๋ฆฌํดํ๋ค.
fetchResults()
: ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ๋ฆฌ์คํธ์ ์ ์ฒด ๊ฐ์๋ฅผ ๋ฆฌํดํ๋ค. ๋ฆฌํด ํ์
์ QueryResults<T>
์ด๋ฉฐ, ๋ด๋ถ์ ์ผ๋ก getResults()
, getTotal()
์ด ์ํ๋๋ค. ๋จ, ์ฑ๋ฅ์ ์ผ๋ก ๋ฌธ์ ๊ฐ ์์ผ๋ฏ๋ก ์ฌ์ฉ์ ์ง์ํ๋ค.
๊ทธ๋ฃนํ๋ฅผ ์ฌ์ฉํ ๋ณต์กํ ์ฟผ๋ฆฌ์์ ์ ํํ ์ ์ฒด ๊ฐ์๋ฅผ ํ์ ํ๊ธฐ ์ด๋ ต๊ณ , ์ ์ฒด ๊ฒฐ๊ณผ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ ํ
size()
๋ก ๊ฐ์๋ฅผ ๊ณ์ฐํ๋ฏ๋ก ์ฑ๋ฅ์ด ์ ํ๋ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.fetch()
ํ ๋ณ๋์ count ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.
fetchCount()
: ์กฐํ ์ฟผ๋ฆฌ๋ฅผ count ์ฟผ๋ฆฌ๋ก ๋ณํํ์ฌ ๊ฐ์๋ฅผ ๋ฆฌํดํ๋ค.
๋ด๋ถ์ ์ผ๋ก
fetch().size()
๋ก ์ฒ๋ฆฌ๋ ๊ฐ๋ฅ์ฑ์ด ์์ด ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ์ด์ ๋ ๋์ผํ๋ค.
์ ๋ ฌ๊ณผ ํ์ด์ง
1
2
3
4
5
6
7
List<Member> members = queryFactory
.selectFrom(member)
.orderBy(member.age.desc(), member.username.asc().nullsLast())
.offset(10)
.limit(5)
.fetch();
orderBy()
: ์ ๋ ฌ ์์๋ฅผ ์ง์ ํ๋ค.
nullsLast()
: null ๊ฐ์ ๋ง์ง๋ง์ ๋ฐฐ์นํ๋ค.
offset()
: ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์์ ๋ช ๋ฒ์งธ ํ๋ถํฐ ๋ฆฌํดํ ์ง ์ง์ ํ๋ค.
limit()
: ์ต๋ ๋ช ๊ฐ์ ํ(ํ์ด์ง ํฌ๊ธฐ)์ ๋ฆฌํดํ ์ง ์ง์ ํ๋ค.
์ง๊ณ ํจ์์ ๊ทธ๋ฃนํ
1
2
3
4
5
6
7
8
9
10
11
List<Tuple> result = queryFactory
.select(
team.name,
member.age.avg()
)
.from(member)
.join(member.team, team)
.groupBy(team.name)
.having(member.age.avg().gt(20))
.fetch();
groupBy()
, having()
: ๊ทธ๋ฃนํํ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋์ด๋ค. avg()
๊ณผ ๊ฐ์ด ๋ค์ํ ์ง๊ณ ํจ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
Projections
1
2
3
4
List<Tuple> result = queryFactory
.select(member.username, member.age)
.from(member)
.fetch();
์ ์ฒด ์ํฐํฐ๊ฐ ์๋ ํ์ํ ํ๋๋ง ์ ํํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๋ ๊ฒฝ์ฐ Projections
๋ฅผ ์ฌ์ฉํ๋ค. QueryDSL์ Tuple
๊ฐ์ฒด๋ฅผ ํตํด ํ๋๋ฅผ ์กฐํํ๋ค.
๊ฒฐ๊ณผ๋ฅผ DTO๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ ํฌ๊ฒ 4๊ฐ์ง๊ฐ ์กด์ฌํ๋ค.
1. Projections.constructor()
1
2
3
4
5
6
7
8
9
List<MemberDto> result = queryFactory
.select(Projections.constructor(
MemberDto.class,
member.username,
member.age
))
.from(member)
.fetch();
DTO์ ์์ฑ์๋ฅผ ํ์ฉํ์ฌ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋งคํํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์์ฑ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋งคํํ๋ฏ๋ก ๋ถ๋ณ DTO๋ฅผ ์์ฑํ ์ ์๋ค. ๋จ, ์ปดํ์ผ ํ์์ ์ค๋ฅ ๊ฒ์ถ์ด ์ด๋ ต๊ณ , ๋งค๊ฐ๋ณ์ ์์๋ฅผ ์ผ์น์์ผ์ผ ํ๋ค. ์์๊ฐ ์ผ์นํ์ง ์์ผ๋ฉด IllegalArgumentException
์ด ๋ฐ์ํ๋ค.
๋ถ๋ณ DTO๋ ํ ๋ฒ ์์ฑ๋ ํ ๋ด๋ถ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ DTO๋ฅผ ๋งํ๋ค. ๋ชจ๋ ํ๋๋
final
๋ก ์ ์ธ๋๋ค.
2. Projections.fields()
1
2
3
4
5
6
7
8
9
List<MemberDto> result = queryFactory
.select(Projections.fields(
MemberDto.class,
member.username,
member.age
))
.from(member)
.fetch();
DTO์ ํ๋์ ์ง์ ์ ๊ทผํ์ฌ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋งคํํ๋ ๋ฐฉ๋ฒ์ด๋ค. DTO์ ํ๋๋ช
๊ณผ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ ํ๋๋ช
์ด ์ผ์นํ๋ฉด ์๋์ผ๋ก ๋งคํ๋๋ค. ์ง์ ๊ฐ์ ์ฃผ์
ํ๋ฏ๋ก Setter๊ฐ ํ์ ์๋ค. ๋จ, DTO์ @NoArgsConstructor
๊ฐ ํ์๋ก ๋ช
์๋์ด์ผ ํ๋ค.
3. Projections.bean()
1
2
3
4
5
6
7
8
9
List<MemberDto> result = queryFactory
.select(Projections.bean(
MemberDto.class,
member.username,
member.age
))
.from(member)
.fetch();
DTO์ Setter๋ฅผ ํตํด ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋งคํํ๋ ๋ฐฉ๋ฒ์ด๋ค. ๋ฐ๋ผ์ Setter์ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ํ์๋ก ๋ช ์๋์ด์ผ ํ๋ค.
4. @QueryProjection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Getter
public class UserDTO {
private String username;
private int age;
@QueryProjection
public UserDTO(String username, int age) {
this.username = username;
this.age = age;
}
}
List<UserDTO> dtos = queryFactory
.select(new QUserDTO(member.username, member.age))
.from(member)
.fetch();
DTO์ ์์ฑ์์ @QueryProjection
์ ์ถ๊ฐํ๋ฉด QueryDSL์ด ํด๋น DTO์ ๋ํ Q-Class๋ฅผ ์๋์ผ๋ก ์์ฑํ์ฌ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ type-safeํ๊ฒ ๋งคํํ ์ ์๋ค. ์์ฑ์ ๊ธฐ๋ฐ์ด๋ฏ๋ก Setter ์์ด ๋ถ๋ณ DTO๋ฅผ ์์ฑํ ์ ์๋ค. ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ฅ ์ถ์ฒํ๋ ๋ฐฉ๋ฒ์ด๋ค.
BooleanBuilder
1
2
3
4
5
6
7
8
9
10
11
12
13
BooleanBuilder builder = new BooleanBuilder();
if (username != null) {
builder.and(member.username.eq(username));
}
if (minAge != null) {
builder.and(member.age.goe(minAge));
}
List<Member> result = queryFactory
.selectFrom(member)
.where(builder)
.fetch();
์กฐ๊ฑด์ ์ ๋์ ์ผ๋ก ์กฐํฉํ๊ณ ์ถ์ ๊ฒฝ์ฐ BooleanBuilder
๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. and()
๋ or()
์ ํตํ ๋ฉ์๋ ์ฒด์ด๋ ๋ฐฉ๋ฒ์ผ๋ก ์์ฑํ ์ ์๋ค.
1
2
BooleanBuilder builder = new BooleanBuilder(Expressions.TRUE);
์กฐ๊ฑด์ด ํ๋๋ ์ถ๊ฐ๋์ง ์๋ ๊ฒฝ์ฐ ์์ ๊ฐ์ด ์์ฑํ๋ค. WHERE 1=1
๊ณผ ๋์ผํ ํจ๊ณผ๋ฅผ ๊ฐ์ง๋ค.
์ฑ๋ฅ์ ์ต์ ํํ๊ธฐ ์ํด ์์ฃผ ๊ฑธ๋ฌ์ง๋ ์กฐ๊ฑด์ ๋จผ์ ์์ฑํ์ฌ ๋ฐ์ดํฐ์ ๋ฒ์๋ฅผ ๋น ๋ฅด๊ฒ ์ถ์ํ๋ ๊ฒ์ด ์ข๋ค.
์กฐ์ธ
1
2
3
4
5
6
7
List<Order> orders = queryFactory
.selectFrom(order)
.join(order.member, member)
.leftJoin(order.product, product)
.where(member.age.gt(30))
.fetch();
QueryDSL์์ ์กฐ์ธ์ JPQL๊ณผ ์ ์ฌํ ๋ฐฉ์์ผ๋ก ์ฌ์ฉ๋๋ค. join()
, innerjoin()
, leftjoin()
, fetchJoin()
๋ฑ๊ณผ ๊ฐ์ ์กฐ์ธ ๋ฉ์๋๊ฐ ์กด์ฌํ๋ฉฐ, on()
์ ํตํด ์กฐ์ธ ์กฐ๊ฑด์ ์ถ๊ฐํ ์ ์๋ค.
์๋ธ์ฟผ๋ฆฌ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// SELECT ์ ์๋ธ์ฟผ๋ฆฌ
List<Tuple> result = queryFactory
.select(
member.username,
JPAExpressions.select(memberSub.age.max())
.from(memberSub)
)
.from(member)
.fetch();
// WHERE ์ ์๋ธ์ฟผ๋ฆฌ
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(
JPAExpressions.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
// FROM ์ ์๋ธ์ฟผ๋ฆฌ
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory
.selectFrom(member)
.from(JPAExpressions.selectFrom(memberSub)
.where(memberSub.age.gt(10)), member)
.fetch();
JPAExpressions
๋ฅผ ํตํด ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋ค. ์๋ธ์ฟผ๋ฆฌ๋ SELECT, WHERE, FROM ์ ์ ์์ฑ๋ ์ ์๋ค.
๋จ, FROM ์ ์๋ธ์ฟผ๋ฆฌ๋ Hibernate 6 ๋ฏธ๋ง์์๋ ์ง์ํ์ง ์๋๋ค.
์กฐ๊ฑด ๋ถ๊ธฐ
1
2
3
4
5
6
7
8
List<String> result = queryFactory
.select(new CaseBuilder()
.when(member.age.between(10, 20)).then("10๋")
.when(member.age.between(20, 30)).then("20๋")
.otherwise("๊ธฐํ"))
.from(member)
.fetch();
CaseBuilder
๋ฅผ ํตํด ๋ณต์กํ ์กฐ๊ฑด ๋ถ๊ธฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค. SQL๋ฌธ์์ CASE WHEN
๊ตฌ๋ฌธ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ํํ๋ค.
์์ ๋ฐ ์ญ์
1
2
3
4
5
6
long count = queryFactory
.update(member)
.set(member.name, newName)
.where(member.name.eq(oldName))
.execute();
update()
์ delete()
๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์์ ๋ฐ ์ญ์ ํ ์ ์๋ค. execute()
๋ฅผ ํตํด ๋ฉ์๋์ ์ํฅ์ ๋ฐ์ ํ์ ์๋ฅผ ๋ฆฌํดํ๋ค.
๐ ์ฐธ๊ณ
https://velog.io/@evan523/JPA-QueryDSL