๐Ÿ”ฅ TIL - Day 59 QueryDSL 1

Kim Dae Hyunยท2021๋…„ 11์›” 18์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
70/93

3์ฐจ ํ”„๋กœ์ ํŠธ ๋•Œ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋Š” ๋˜๋„๋ก QueryDsl์„ ์‚ฌ์šฉํ•ด๊ณ ์ž ์•Œ์•„๋ดค๋‹ค.

Springboot์˜ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋น„ํ•ด ์„ค์ •์ด ๋ณต์žกํ•˜๋‹ค.

์ „์ฒด์ฝ”๋“œ Github

๐Ÿ“Œ ์„ค์ • ใ… 

plugins {
    id 'org.springframework.boot' version '2.4.12'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.dhk'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    // ==== Query dsl ==== //
    implementation 'com.querydsl:querydsl-jpa'
    // Qํด๋ž˜์Šค ์ƒ์„ฑ์„ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
    annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
    annotationProcessor "jakarta.persistence:jakarta.persistence-api"
    annotationProcessor "jakarta.annotation:jakarta.annotation-api"
}

test {
    useJUnitPlatform()
}

ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๋„๋ฉ”์ธ์„ ์ž‘์„ฑํ•œ๋‹ค.
์ฒ˜์Œ ์ ‘ํ•˜๋Š” ๊ธฐ์ˆ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋„๋ฉ”์ธ์€ ๋งค์šฐ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ–ˆ๋‹ค.

User ์—”ํ‹ฐํ‹ฐ

@Entity
@NoArgsConstructor
@Getter
public class User {

    @Id @GeneratedValue
    private Long id;
    @Column(nullable = false)
    private String username;
    @Column(nullable = false)
    private String password;

    private int age;

    @JoinColumn(name = "team_id")
    @ManyToOne(fetch = FetchType.LAZY)
    private Team team;

    public void setTeam(Team team) {
        this.team = team;
    }

    public User(String username, String password, int age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }
}

Team ์—”ํ‹ฐํ‹ฐ

@Entity
@NoArgsConstructor
@Getter
public class Team {

    @Id @GeneratedValue
    private Long id;
    @Column(nullable = false)
    private String teamName;

    private int teamAge; // ํŒ€์ด ์ƒ๊ธด์ง€ ๋ช‡ ๋…„ ๋๋Š”์ง€... ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์–ต์ง€๋กœ ..ใ…Ž

    public Team(String teamName, int teamAge) {
        this.teamName = teamName;
        this.teamAge = teamAge;
    }
}

์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  Entity๋ฅผ QueryDsl์—์„œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์—”ํ‹ฐํ‹ฐ์— ๋Œ€์‘๋˜๋Š” Qํƒ€์ž… ํด๋ž˜์Šค๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
์•ž์„œ Gradle ์„ค์ •์œผ๋กœ Qํƒ€์ž… ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ์ด๋‹ค.

Gradle ํ…Œ์Šคํฌ์˜ ๋„์›€์„ ๋ฐ›์•„ Qํƒ€์ž… ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์•„๋ž˜ ๊ฒฝ๋กœ๋กœ ์ƒ์„ฑ๋œ๋‹ค.
์ƒ์„ฑ๋˜๋Š” ๊ฒฝ๋กœ๋Š” build.gradle์—์„œ ๋ณ€๊ฒฝ๊ฐ€๋Šฅํ•˜๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ QueryDsl ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋นˆ์„ ํ•˜๋‚˜ ๋“ฑ๋กํ•ด์ค˜์•ผ ํ•œ๋‹ค.
์ด์ œ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ EntityManager๊ฐ€ ์•„๋‹ˆ๊ณ  JPAQueryFactory๋ฅผ ์ฃผ์ž…๋ฐ›์•„์„œ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค. QueryDsl์˜ EntityManager๋Š” JPAQueryFactory์ด๋‹ค ๋ผ๊ณ  ์ดํ•ดํ•ด๋„ ๋  ๋“ฏํ•˜๋‹ค.

@RequiredArgsConstructor
@Configuration
public class AppConfig {

    private final EntityManager em;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(em);
    }
}



๋“ฑ๋กํ•œ JPAQueryFactory๋ฅผ ์ฃผ์ž…๋ฐ›์•„ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

@Autowired 
private JPAQueryFactory query;

๐Ÿ“Œ QueryDSL ๋ง›๋ณด๊ธฐ

selectFrom์€ *์™€ ๊ฐ™์€ ์˜๋ฏธ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.
์—ฌ๊ธฐ์„œ user๋Š” Qํƒ€์ž…์˜ QUserํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์ด๋‹ค. static์œผ๋กœ ์„ ์–ธ๋˜์–ด ์žˆ์–ด์„œ static importํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.

    @Order(1)
    @DisplayName("1. ๊ธฐ๋ณธ์กฐํšŒ ์กฐ๊ฑด์—†์ด ๋ชจ๋‘ ์กฐํšŒ")
    @Test
    void ๊ธฐ๋ณธ์กฐํšŒ() {
        // select * from user;
        List<User> users = query.selectFrom(user) // QUser.user ==> user
                .fetch(); 

        users.forEach(u -> System.out.println(u.getUsername()));
    }

์กฐ๊ฑด์—†๋Š” finAll์€ ์“ธ ์ผ์ด ์—†๋‹ค. ์กฐ๊ฑด์„ ํ•˜๋‚˜์”ฉ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

์กฐํšŒ + ์กฐ๊ฑด

์กฐ๊ฑด๋“ค์ด ๊ต‰์žฅํžˆ ์ง๊ด€์ ์ด๋‹ค.
equal, greater than, less than, greater or equals, less or equals ...
๋Š๋‚Œ์ ์œผ๋กœ IDE์˜ ๋„์›€์„ ๋ฐ›์œผ๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

    @Order(2)
    @Test
    @DisplayName("2. ๊ธฐ๋ณธ์กฐํšŒ where ์ ˆ ํฌํ•จ")
    void ๊ธฐ๋ณธ์กฐํšŒ_where() {
        // select * from user where username = test1;
        List<User> users = query.selectFrom(user)
                .where(user.username.eq("test1"))
                .fetch();

        users.forEach(u -> System.out.println(u.getUsername()));
    }
    
    @Test
    @DisplayName("2-1 ๊ธฐ๋ณธ์กฐํšŒ where์ ˆ ํฌํž˜")
    void ๊ธฐ๋ณธ์กฐํšŒ_where2() {
        // select * from user where age between 20 and 30;
        List<User> users = query.selectFrom(user)
                .where(user.age.between(20, 30))
                .fetch();
        users.forEach(u -> System.out.println(u.getUsername()));
    }

์ •๋ ฌ

    @Test
    @DisplayName("3. ์ •๋ ฌ")
    void ๋‚˜์ด_์ •๋ ฌ_์˜ค๋ฆ„์ฐจ์ˆœ() {
        // ํŒ€1์— ์†ํ•œ user๋ฅผ ๋‚˜์ด์ˆœ์œผ๋กœ ์ •๋ ฌ
        /**
         * select * from user u
         * join team t
         * where u.team_id = t.id and t.name = team1
         * orderBy u.age asc;
          */
        List<User> users = query.selectFrom(QUser.user)
                .where(user.team.teamName.eq("team1"))
                .orderBy(QUser.user.age.asc())
                .fetch();
        users.forEach(u -> System.out.println(u.getAge()));
    }

ํŽ˜์ด์ง•

๋ฐ˜ํ™˜ํƒ€์ž…์ด QueryReult์ด๋‹ค.
JPA์˜ Page๊ฐ์ฒด์™€ ๋น„์Šทํ•œ ํ˜•ํƒœ์ด๋‹ค. ํŽ˜์ด์ง•์— ๋Œ€ํ•œ ์ •๋ณด์™€ ๋ฆฌ์ŠคํŠธํ˜•ํƒœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค.

    @Order(5)
    @Test
    @DisplayName("4. ํŽ˜์ด์ง•")
    void ํŽ˜์ด์ง•() {
        QueryResults<User> queryResults = query.selectFrom(user)
                .offset(1)
                .limit(3)
                .fetchResults();

        List<User> users = queryResults.getResults();
        for (User user1 : users) {
            System.out.println(user1.getUsername());
        }

        System.out.println("offset = " + queryResults.getOffset());
        System.out.println("limit = " + queryResults.getLimit());
        System.out.println("total = " + queryResults.getTotal());
    }

Join

(User์™€ Team์€ ManyToOne ๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„์ด๋‹ค)

    @Order(6)
    @Test
    @DisplayName("5. Join")
    void join1() {
        // team, user inner join
        List<User> users = query.selectFrom(user)
                .join(user.team, team)
                .fetch();

        users.forEach(u -> System.out.println(u.getUsername()));

        assertEquals(4, users.size());
    }

left join๋„ ํ‚ค์›Œ๋“œ๋งŒ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

    @Test
    @DisplayName("6. left join")
    void leftJoin() {
        List<User> users = query.selectFrom(user)
                .leftJoin(user.team, team)
                .fetch();

        users.forEach(u -> System.out.println(u.getUsername()));

        assertEquals(6, users.size());
    }

Subquery
์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” JPAExpression์„ ํ†ตํ•ด ๊ฐ€๋Šฅํ•˜๋‹ค.
where์ ˆ์—์„œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ…Œ์ŠคํŠธ์ด๋‹ค.

Qํƒ€์ž… ํด๋ž˜์Šค์˜ ํ•„๋“œ์—์„œ ์ง‘๊ณ„์ฟผ๋ฆฌ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ๋„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. (max())

    @Test
    @DisplayName("7. where์ ˆ ์„œ๋ธŒ์ฟผ๋ฆฌ")
    void whereSubquery() {


        List<User> users = query.selectFrom(user)
                .where(user.age.in(
                        JPAExpressions
                                .select(team.teamAge.max())
                                .from(team)
                ))
                .fetch();

        assertEquals(1, users.size());
    }

Case ์ฟผ๋ฆฌ
์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณธ ์ ์€ ์—†๋Š”๋ฐ ์ถฉ๋ถ„ํžˆ ์จ์•ผ ํ•  ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.
CaseBuilder๋ฅผ ์ด์šฉํ•ด์„œ when-then ์ ˆ๋กœ Case๋ฌธ์„ ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ๋‹ค.

    @Test
    @DisplayName("8. case ์ฟผ๋ฆฌ")
    void caseQuery() {

        List<String> results = query
                .select(new CaseBuilder()
                        .when(user.age.loe(30)).then("์ฃผ๋‹ˆ์–ด")
                        .when(user.age.goe(31)).then("์‹œ๋‹ˆ์–ด")
                        .otherwise("์–ด๋ฆฐ์ด: " + user.age)
                ).from(user)
                .fetch();

        results.forEach(System.out::println);
    }

ํ”„๋กœ์ ์…˜
ํ”„๋กœ์ ์…˜์€ ํ•œ ๋ฆด๋ ˆ์ด์…˜์—์„œ ํ•„์š”ํ•œ Attribute(์นผ๋Ÿผ)๋งŒ ๋ฝ‘์•„์˜ค๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.
ํ”„๋กœ์ ์…˜์„ ํ•˜๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์€๋ฐ ์—ฌ๋Ÿฌ ๊ธ€์—์„œ DTO ์ƒ์„ฑ์ž๋ฅผ ์ด์šฉํ•œ ํ”„๋กœ์ ์…˜์„ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ผฝ๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด ๋ฐฉ๋ฒ•์ด ์›๋ž˜ JPA์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๊ฐ€์žฅ ๋น„์Šทํ•œ ๊ฐ™๋‹ค.

ํ”„๋กœ์ ์…˜์˜ ๋Œ€์ƒ์ด ๋  DTO๋ฅผ ์ •์˜ํ•œ๋‹ค.
์ชผ๊ธˆ ๋ถˆํŽธํ•œ ๋ถ€๋ถ„์ด ์ด DTO ํด๋ž˜์Šค๋ฅผ QueryDsl์—์„œ ํ”„๋กœ์ ์…˜ ๋Œ€์ƒ ํด๋ž˜์Šค๋กœ ์“ฐ๋ ค๋ฉด ์ด ํด๋ž˜์Šค์— ๋Œ€ํ•œ Qํƒ€์ž… ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด์ค˜์•ผ ํ•œ๋‹ค.

@QueryProjection์„ ์ƒ์„ฑ์ž์— ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ  Gradle tasks - other์˜ compile์„ ๋‹ค์‹œ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

@NoArgsConstructor
@Data
public class UserDto {
    private String username;
    private int age;
    private String teamName;

    @QueryProjection // Qํƒ€์ž… ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•จ
    public UserDto(String username, int age, String teamName) {
        this.username = username;
        this.age = age;
        this.teamName = teamName;
    }
}

JPA์—์„œ๋Š” DTO๋กœ ์กฐํšŒํ•  ๋•Œ new ํ‚ค์›Œ๋“œ์™€ ํ•ด๋‹น DTO์˜ ํŒจํ‚ค์ง€๋ฅผ ๋ชจ๋‘ ์ ์–ด์ฃผ๋Š” ๋ฐฉ์‹์ด์˜€๋‹ค.
Query dsl์—์„œ๋„ ๋™์ผํ•˜๊ฒŒ new๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ํŒจํ‚ค์ง€๋Š” ์ ์–ด์ฃผ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

    @Test
    @DisplayName("9. ํ”„๋กœ์ ์…˜ - DTO์˜ ์ƒ์„ฑ์ž ์‚ฌ์šฉ")
    void ํ”„๋กœ์ ์…˜_DTO() {

        List<UserDto> userDtos = query.select(new QUserDto(user.username, user.age, team.teamName))
                .from(user)
                .join(user.team, team)
                .fetch();

        userDtos.forEach(ut -> System.out.println(ut.getUsername() + ": "+ ut.getTeamName()));
    }

๋™์ ์ฟผ๋ฆฌ

ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์ฟผ๋ฆฌ์— ํฌํ•จ๋˜๋Š” ๋™์ ์ฟผ๋ฆฌ๋Š” ๋งค์šฐ ์ž์ฃผ ์“ฐ์ธ๋‹ค.
JPA์—์„œ ์ด๋Ÿฐ ๋™์ ์ฟผ๋ฆฌ๋ฅผ ์ด์šฉํ•  ๋•Œ ๋„ค์ด๋ฐ ์ฟผ๋ฆฌ๋กœ ๋ณต์žก์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋„ค์ด๋ฐ ์ฟผ๋ฆฌ์˜ ๊ฒฝ์šฐ ํ•œ๊ณ„๊ฐ€ ์žˆ๋‹ค.

๋•Œ๋ฌธ์— ์ง์ ‘ JPQL์„ ์งœ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ ์ด ๋•Œ ์ฟผ๋ฆฌ๊ฐ€ ๋ชจ๋‘ ๋ฌธ์ž์—ด๋กœ ์ž‘์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ฟผ๋ฆฌ์ž์ฒด๊ฐ€ ์กฐ๊ธˆ ๋ณต์žกํ•ด์ง„๋‹ค๋ฉด JPQL ์ž‘์„ฑ์€ ๋”๋”๋”๋” ์–ด๋ ค์›Œ์ง„๋‹ค. ์–ด๋ ค์›Œ์ง€๋Š” ๊ฒƒ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์—๋Ÿฌ์˜ ๊ฐ€๋Šฅ์„ฑ ๋˜ํ•œ ๋†’์•„์ง„๋‹ค. ์ด๋Ÿฐ ์—๋Ÿฌ๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์— ์บ์น˜๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋” ๊ณ ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ Intellij๊ฐ€ ๋ถ€์กฑํ•œ ๋‚˜์˜ ๊ธธ์žก์ด๊ฐ€ ๋˜์–ด์ค€๋‹ค. ๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘

์ด๋ฅผ ์œ„ํ•ด Querydsl์˜ ๋™์ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์ด์ œ ๋ง‰ Querydsl ์ชผ๊ธˆ ์•Œ๊ฒŒ ๋œ ๊ฒƒ์ด์ง€๋งŒ ์•ž์„œ ํ–ˆ๋˜ ๊ฒƒ๋“ค์€ ์†”์งํžˆ JPA๊ฐ€ ๋” ํŽธํ•˜์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค. ํ•˜์ง€๋งŒ ๋™์ ์ฟผ๋ฆฌ์˜ ๊ฒฝ์šฐ ํ•ด๋ณด ๊ฒฐ๊ณผ ์žฅ์ ์ด ๋งค์šฐ ๋งŽ๋‹ค. ์ž˜ ๊ธฐ์–ตํ•˜๊ณ  ํ™œ์šฉํ•ด๋ณด์ž.

    @Test
    @DisplayName("10. ๋™์ ์ฟผ๋ฆฌ1")
    void ๋™์ ์ฟผ๋ฆฌ1() {
        List<UserDto> userDtos = getUserByUsernameAndTeamName("user1", "team1");

        userDtos.forEach(ut -> System.out.println(ut.getUsername() + ": "+ ut.getTeamName()));
        assertEquals(1, userDtos.size());
    }

    private List<UserDto> getUserByUsernameAndTeamName(String username, String teamName) {

        BooleanBuilder builder = new BooleanBuilder();
        if (!Objects.isNull(username)) {
            builder.and(user.username.eq(username));
        }
        if (!Objects.isNull(teamName)) {
            builder.and(team.teamName.eq(teamName));
        }

        return query
                .select(new QUserDto(user.username, user.age, team.teamName))
                .from(user)
                .join(user.team, team)
                .where(builder)
                .fetch();
    }

BooleanBuilder๋ฅผ ์ด์šฉํ•ด์„œ ์กฐ๊ฑด์„ ์Œ“๋Š”๋‹ค.
BooleanBuilder๋ฅผ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฒฐ๊ณผ๋Š” BooleanExpresson์ด๊ณ  ์ด ๊ฐ์ฒด๊ฐ€ where ์ ˆ์˜ ์กฐ๊ฑด์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋Œ€ํ•œ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์ •์ƒ์ด๋ผ๋ฉด Qํƒ€์ž… ์ธ์Šคํ„ด์Šค๋ฅผ ์ด์šฉํ•ด์„œ ์กฐ๊ฑด์„ ๊ตฌ์„ฑํ•˜๊ณ  builder๋ฅผ where์ ˆ์— ๋„ฃ์–ด์ค€๋‹ค.

์ปดํŒŒ์ผ ์‹œ์ ์— ์—๋Ÿฌ๋ฅผ ์žก์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ์•Œ๊ฒ ๋‹ค. ๊ทผ๋ฐ ์ข€ ์ง€๋‚˜์น˜๊ฒŒ ๊ธธ์–ด์ง€๋Š”๊ฒŒ ์•„๋‹Œ๊ฐ€ ์‹ถ๋‹ค.
๋‘๋ฒˆ์งธ ์žฅ์ ์ด ๋‚˜์™€์ค˜์•ผ ํ•œ๋‹ค.

    @Test
    @DisplayName("11. ๋™์ ์ฟผ๋ฆฌ2 ์กฐ๊ฑด ๋ฉ”์„œ๋“œ๋กœ ๋นผ๋‚ด๊ธฐ")
    void ๋™์ ์ฟผ๋ฆฌ2() {

        List<UserDto> userDtos = query
                .select(new QUserDto(user.username, user.age, team.teamName))
                .from(user)
                .join(user.team, team)
                .where(ageGreaterThanEquals(20), teamNameEquals("team3")) // and๋กœ ์—ฐ๊ฒฐ
                .fetch();

        assertEquals(1, userDtos.size());
    }

    private BooleanExpression ageGreaterThanEquals(int age) {
        return age <= 0 ? null : user.age.goe(age);
    }

    private BooleanExpression teamNameEquals(String teamName) {
        return Objects.isNull(teamName) ? null : team.teamName.eq(teamName);
    }

๊ตฌ์กฐ์™€ ๊ธฐ๋Šฅ์€ ์กฐ๊ธˆ ๋ฐ”๋€Œ์—ˆ์ง€๋งŒ ๊ฐ๊ฐ ํ•˜๋‚˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›๋Š” ๋‘ ๊ฐœ ์กฐ๊ฑด์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์€ ๋™์ผํ•˜๋‹ค.
์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์กฐ๊ฑด๋ฌธ ์ž์ฒด๋ฅผ ๋ฉ”์„œ๋“œํ™” ํ–ˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์žฌ์‚ฌ์šฉ์˜ ์—ฌ์ง€๊ฐ€ ์ƒ๊ฒผ๋‹ค!
wow



profile
์ข€ ๋” ์ฒœ์ฒœํžˆ ๊นŒ๋จน๊ธฐ ์œ„ํ•ด ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ๐Ÿง

0๊ฐœ์˜ ๋Œ“๊ธ€