|
1 | 1 | package study.querydsl;
|
2 | 2 |
|
| 3 | +import com.querydsl.core.BooleanBuilder; |
3 | 4 | import com.querydsl.core.QueryResults;
|
4 | 5 | import com.querydsl.core.Tuple;
|
5 | 6 | import com.querydsl.core.types.Expression;
|
| 7 | +import com.querydsl.core.types.ExpressionUtils; |
| 8 | +import com.querydsl.core.types.Predicate; |
| 9 | +import com.querydsl.core.types.Projections; |
| 10 | +import com.querydsl.core.types.dsl.BooleanExpression; |
6 | 11 | import com.querydsl.core.types.dsl.Expressions;
|
7 | 12 | import com.querydsl.jpa.JPAExpressions;
|
8 | 13 | import com.querydsl.jpa.impl.JPAQuery;
|
|
11 | 16 | import org.junit.jupiter.api.Test;
|
12 | 17 | import org.springframework.beans.factory.annotation.Autowired;
|
13 | 18 | import org.springframework.boot.test.context.SpringBootTest;
|
| 19 | +import org.springframework.test.annotation.Commit; |
14 | 20 | import org.springframework.transaction.annotation.Transactional;
|
| 21 | +import study.querydsl.dto.MemberDto; |
| 22 | +import study.querydsl.dto.QMemberDto; |
| 23 | +import study.querydsl.dto.UserDto; |
15 | 24 | import study.querydsl.entity.*;
|
16 | 25 |
|
17 | 26 | import javax.persistence.EntityManager;
|
@@ -429,5 +438,278 @@ public void constant() {
|
429 | 438 | }
|
430 | 439 | }
|
431 | 440 |
|
| 441 | + // 프로젝션 대상 하나 인경우 |
| 442 | + @Test |
| 443 | + public void simpleProjection() { |
| 444 | + List<String> usernames = jpaQueryFactory |
| 445 | + .select(member.username) |
| 446 | + .from(member) |
| 447 | + .fetch(); |
| 448 | + |
| 449 | + List<Member> members = jpaQueryFactory |
| 450 | + .selectFrom(member) |
| 451 | + .fetch(); |
| 452 | + |
| 453 | + for (String username : usernames) { |
| 454 | + System.out.println("username = " + username); |
| 455 | + } |
| 456 | + |
| 457 | + for (Member member1 : members) { |
| 458 | + System.out.println("member1 = " + member1); |
| 459 | + } |
| 460 | + } |
| 461 | + |
| 462 | + // 투플의 경우, 레파지토리 계층에서만 사용 권장 |
| 463 | + // dto로 변환 후 사용권장 |
| 464 | + @Test |
| 465 | + public void tupleProjection() { |
| 466 | + List<Tuple> tuples = jpaQueryFactory |
| 467 | + .select(member.username, member.age) |
| 468 | + .from(member) |
| 469 | + .fetch(); |
| 470 | + |
| 471 | + for (Tuple tuple : tuples) { |
| 472 | + System.out.println("tuple.get(member.username) = " + tuple.get(member.username)); |
| 473 | + System.out.println("tuple.get(member.age) = " + tuple.get(member.age)); |
| 474 | + } |
| 475 | + } |
| 476 | + |
| 477 | + // jpa dto 조회 |
| 478 | + @Test |
| 479 | + public void findDto() { |
| 480 | + List<MemberDto> memberDtos = em.createQuery("select new study.querydsl.dto.MemberDto(m.username, m.age) from Member m", MemberDto.class) |
| 481 | + .getResultList(); |
| 482 | + for (MemberDto memberDto : memberDtos) { |
| 483 | + System.out.println("memberDto = " + memberDto); |
| 484 | + } |
| 485 | + } |
| 486 | + |
| 487 | + |
| 488 | + // dto => 기본생성자 존재해야함 |
| 489 | + // setter 주입 |
| 490 | + // getter, setter 존재해야함 |
| 491 | + @Test |
| 492 | + public void findDtoByQuerydsl() { |
| 493 | + List<MemberDto> memberDtos = jpaQueryFactory |
| 494 | + .select(Projections.bean(MemberDto.class, member.username, member.age)) |
| 495 | + .from(member) |
| 496 | + .fetch(); |
| 497 | + for (MemberDto memberDto : memberDtos) { |
| 498 | + System.out.println("memberDto = " + memberDto); |
| 499 | + } |
| 500 | + } |
| 501 | + |
| 502 | + // 필드 입 : getter, setter 없어도됨 |
| 503 | + @Test |
| 504 | + public void findDtoByFields() { |
| 505 | + List<MemberDto> memberDtos = jpaQueryFactory |
| 506 | + .select(Projections.fields(MemberDto.class, member.username, member.age)) |
| 507 | + .from(member) |
| 508 | + .fetch(); |
| 509 | + for (MemberDto memberDto : memberDtos) { |
| 510 | + System.out.println("memberDto = " + memberDto); |
| 511 | + } |
| 512 | + } |
| 513 | + |
| 514 | + //생성자 주입 |
| 515 | + @Test |
| 516 | + public void findDtoByConstructor() { |
| 517 | + List<MemberDto> memberDtos = jpaQueryFactory |
| 518 | + .select(Projections.constructor(MemberDto.class, member.username, member.age)) |
| 519 | + .from(member) |
| 520 | + .fetch(); |
| 521 | + for (MemberDto memberDto : memberDtos) { |
| 522 | + System.out.println("memberDto = " + memberDto); |
| 523 | + } |
| 524 | + } |
| 525 | + |
| 526 | + // 필드주입 - 필드이름 = 엔티티이름 같아야함 |
| 527 | + // 다를 경우, as 사용 |
| 528 | + @Test |
| 529 | + public void findDtoByUserDto() { |
| 530 | + QMember memberSub = new QMember("memberSub"); |
| 531 | + |
| 532 | + List<UserDto> memberDtos = jpaQueryFactory |
| 533 | + .select(Projections.fields(UserDto.class, member.username.as("name"), |
| 534 | + ExpressionUtils.as(JPAExpressions |
| 535 | + .select(memberSub.age.max()) |
| 536 | + .from(memberSub), "age" |
| 537 | + ) |
| 538 | + ) |
| 539 | + ) |
| 540 | + .from(member) |
| 541 | + .fetch(); |
| 542 | + for (UserDto memberDto : memberDtos) { |
| 543 | + System.out.println("memberDto = " + memberDto); |
| 544 | + } |
| 545 | + } |
| 546 | + |
| 547 | + // 생성자 주입 - 타입만 같으면 가능 |
| 548 | + @Test |
| 549 | + public void findDtoByUserDtoByConstructor() { |
| 550 | + QMember memberSub = new QMember("memberSub"); |
| 551 | + |
| 552 | + List<UserDto> memberDtos = jpaQueryFactory |
| 553 | + .select(Projections.constructor(UserDto.class, member.username, |
| 554 | + JPAExpressions |
| 555 | + .select(memberSub.age.max()) |
| 556 | + .from(memberSub) |
| 557 | + |
| 558 | + ) |
| 559 | + ) |
| 560 | + .from(member) |
| 561 | + .fetch(); |
| 562 | + for (UserDto memberDto : memberDtos) { |
| 563 | + System.out.println("memberDto = " + memberDto); |
| 564 | + } |
| 565 | + } |
| 566 | + |
| 567 | + |
| 568 | + // 컴파일 에러 잡기 가능 |
| 569 | + // dto -> querydsl에 대한 의존성이 생김 (순수한 dto라 볼수없음) |
| 570 | + // 아키텍쳐에 따라 유연하게 결정 |
| 571 | + @Test |
| 572 | + public void findDtoByQueryProjection() { |
| 573 | + List<MemberDto> memberDtos = jpaQueryFactory |
| 574 | + .select(new QMemberDto(member.username, member.age)) |
| 575 | + .from(member) |
| 576 | + .fetch(); |
| 577 | + for (MemberDto memberDto : memberDtos) { |
| 578 | + System.out.println("memberDto = " + memberDto); |
| 579 | + } |
| 580 | + } |
| 581 | + |
| 582 | + |
| 583 | + // 동적쿼리 - 이름,나이 존재하면 where 절에 조건넣음 |
| 584 | + @Test |
| 585 | + public void dynamicQuery_BooleanBuilder() { |
| 586 | + String usernameParam = "member1"; |
| 587 | + Integer ageParam = null; |
| 588 | + |
| 589 | + List<Member> result = searchMember1(usernameParam, ageParam); |
| 590 | + assertThat(result.size()).isEqualTo(1); |
| 591 | + } |
| 592 | + |
| 593 | + // |
| 594 | + private List<Member> searchMember1(String usernameCond, Integer ageCond) { |
| 595 | + BooleanBuilder builder = new BooleanBuilder(); |
| 596 | + if (usernameCond != null) { |
| 597 | + builder.and(member.username.eq(usernameCond)); |
| 598 | + } |
| 599 | + |
| 600 | + if (ageCond != null) { |
| 601 | + builder.and(member.age.eq(ageCond)); |
| 602 | + } |
| 603 | + |
| 604 | + List<Member> result = jpaQueryFactory |
| 605 | + .selectFrom(member) |
| 606 | + .where(builder) |
| 607 | + .fetch(); |
| 608 | + |
| 609 | + return result; |
| 610 | + } |
| 611 | + |
| 612 | + // where 절에 null 이면 무시 |
| 613 | + // where 절 가독성 좋음 |
| 614 | + //querydsl - 재사용성 가능 (자바코드이기 때문에) |
| 615 | + @Test |
| 616 | + public void dynamicQueryWhere() { |
| 617 | + String usernameParam = "member1"; |
| 618 | + Integer ageParam = null; |
| 619 | + |
| 620 | + List<Member> result = searchMember2(usernameParam, ageParam); |
| 621 | + assertThat(result.size()).isEqualTo(1); |
| 622 | + } |
| 623 | + |
| 624 | + private List<Member> searchMember2(String usernameCond, Integer ageCond) { |
| 625 | + return jpaQueryFactory |
| 626 | + .selectFrom(member) |
| 627 | + .where(allEq(usernameCond, ageCond)) |
| 628 | + .fetch(); |
| 629 | + } |
| 630 | + |
| 631 | + private BooleanExpression ageEq(Integer ageCond) { |
| 632 | + return ageCond != null ? member.age.eq(ageCond) : null; |
| 633 | + } |
| 634 | + |
| 635 | + private BooleanExpression usernameEq(String usernameCond) { |
| 636 | + return usernameCond != null? member.username.eq(usernameCond) : null; |
| 637 | + } |
| 638 | + |
| 639 | + // 컴포지션 가능 |
| 640 | + private Predicate allEq(String usernameCond, Integer ageCond) { |
| 641 | + return usernameEq(usernameCond).and(ageEq(ageCond)); |
| 642 | + } |
| 643 | + |
| 644 | + //벌크연산 |
| 645 | + @Test |
| 646 | + public void bulkUpdate() { |
| 647 | + long count = jpaQueryFactory |
| 648 | + .update(member) |
| 649 | + .set(member.username, "비회원") |
| 650 | + .where(member.age.lt(28)) |
| 651 | + .execute(); |
| 652 | + |
| 653 | + em.clear(); |
| 654 | + |
| 655 | + // 나이 1 빼기 |
| 656 | +// long count2 = jpaQueryFactory |
| 657 | +// .update(member) |
| 658 | +// .set(member.age, member.age.add(-1)) |
| 659 | +// .execute(); |
| 660 | + |
| 661 | + |
| 662 | + List<Member> result = jpaQueryFactory |
| 663 | + .selectFrom(member) |
| 664 | + .fetch(); |
| 665 | + for (Member member1 : result) { |
| 666 | + System.out.println("member1 = " + member1.getUsername()); |
| 667 | + } |
| 668 | + |
| 669 | + } |
| 670 | + |
| 671 | + //벌크 삭제 |
| 672 | + @Test |
| 673 | + public void deleteBulk() { |
| 674 | + long count = jpaQueryFactory |
| 675 | + .delete(member) |
| 676 | + .where(member.age.lt(18)) |
| 677 | + .execute(); |
| 678 | + |
| 679 | + } |
| 680 | + |
| 681 | + //sql function : ex) replace 함수 |
| 682 | + @Test |
| 683 | + public void sqlFunction() { |
| 684 | + List<String> result = jpaQueryFactory |
| 685 | + .select( |
| 686 | + Expressions.stringTemplate("function('regexp_replace', {0}, {1}, {2})", |
| 687 | + member.username, |
| 688 | + "member", |
| 689 | + "M") |
| 690 | + ).from(member) |
| 691 | + .fetch(); |
| 692 | + |
| 693 | + for (String s : result) { |
| 694 | + System.out.println("s = " + s); |
| 695 | + } |
| 696 | + } |
| 697 | + |
| 698 | + // 소문자 함수 |
| 699 | + @Test |
| 700 | + public void sqlFunction2() { |
| 701 | + List<String> result = jpaQueryFactory |
| 702 | + .select(member.username) |
| 703 | + .from(member) |
| 704 | +// .where(member.username.eq(Expressions.stringTemplate("function('lower', {0})", member.username))) |
| 705 | + .where(member.username.eq(member.username.lower())) |
| 706 | + .fetch(); |
| 707 | + |
| 708 | + for (String s : result) { |
| 709 | + System.out.println("s = " + s); |
| 710 | + } |
| 711 | + } |
| 712 | + |
| 713 | + |
432 | 714 |
|
433 | 715 | }
|
0 commit comments