diff --git a/querydsl/db.mv.db b/querydsl/db.mv.db index 5b557e6c..e4925e94 100644 Binary files a/querydsl/db.mv.db and b/querydsl/db.mv.db differ diff --git a/querydsl/src/main/java/com/example/querydsl/dto/MemberDto.java b/querydsl/src/main/java/com/example/querydsl/dto/MemberDto.java new file mode 100644 index 00000000..355b723b --- /dev/null +++ b/querydsl/src/main/java/com/example/querydsl/dto/MemberDto.java @@ -0,0 +1,20 @@ +package com.example.querydsl.dto; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class MemberDto { + + private String username; + private int age; + + @QueryProjection + public MemberDto(String username, int age) { + this.username = username; + this.age = age; + } +} diff --git a/querydsl/src/main/java/com/example/querydsl/dto/UserDto.java b/querydsl/src/main/java/com/example/querydsl/dto/UserDto.java new file mode 100644 index 00000000..c2806bea --- /dev/null +++ b/querydsl/src/main/java/com/example/querydsl/dto/UserDto.java @@ -0,0 +1,9 @@ +package com.example.querydsl.dto; + +import lombok.Data; + +@Data +public class UserDto { + private String name; + private int age; +} diff --git a/querydsl/src/test/java/com/example/querydsl/QuerydslBasicTest.java b/querydsl/src/test/java/com/example/querydsl/QuerydslBasicTest.java index 7f7edfe1..1fd4897c 100644 --- a/querydsl/src/test/java/com/example/querydsl/QuerydslBasicTest.java +++ b/querydsl/src/test/java/com/example/querydsl/QuerydslBasicTest.java @@ -1,11 +1,19 @@ package com.example.querydsl; +import com.example.querydsl.dto.MemberDto; +import com.example.querydsl.dto.QMemberDto; +import com.example.querydsl.dto.UserDto; import com.example.querydsl.entity.Member; import com.example.querydsl.entity.QMember; import com.example.querydsl.entity.QTeam; import com.example.querydsl.entity.Team; +import com.querydsl.core.BooleanBuilder; import com.querydsl.core.QueryResults; import com.querydsl.core.Tuple; +import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.Predicate; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; @@ -15,6 +23,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.Commit; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; @@ -448,4 +457,279 @@ public class QuerydslBasicTest { System.out.println("s = " + s); } } + + @Test + void simpleProjection() { + List result = queryFactory + .select(member.username) + .from(member) + .fetch(); + + for (String s : result) { + System.out.println("s = " + s); + } + } + + @Test + void tupleProjection() { + List result = queryFactory + .select(member.username, member.age) + .from(member) + .fetch(); + + for (Tuple tuple : result) { + String username = tuple.get(member.username); + Integer age = tuple.get(member.age); + System.out.println("username = " + username); + System.out.println("age = " + age); + } + } + + @Test + void findDtoByJPQL() { + List result = + em.createQuery("select new com.example.querydsl.dto.MemberDto(m.username, m.age) from Member m", MemberDto.class) + .getResultList(); + + for (MemberDto memberDto : result) { + System.out.println("memberDto = " + memberDto); + } + } + + @Test + void findDtoBySetter() { + List result = queryFactory + .select(Projections.bean(MemberDto.class, + member.username, + member.age)) + .from(member) + .fetch(); + + for (MemberDto memberDto : result) { + System.out.println("memberDto = " + memberDto); + } + } + + @Test + void findDtoByField() { + List result = queryFactory + .select(Projections.fields(MemberDto.class, + member.username, + member.age)) + .from(member) + .fetch(); + + for (MemberDto memberDto : result) { + System.out.println("memberDto = " + memberDto); + } + } + + @Test + void findDtoByConstructor() { + List result = queryFactory + .select(Projections.constructor(MemberDto.class, // 생성자는 타입으로 매칭 이름 달라도 됨 + member.username, + member.age)) + .from(member) + .fetch(); + + for (MemberDto memberDto : result) { + System.out.println("memberDto = " + memberDto); + } + } + + @Test + void findUserDto() { + List result = queryFactory + .select(Projections.fields(UserDto.class, + member.username.as("name"), + member.age)) + .from(member) + .fetch(); + + for (UserDto userDto : result) { + System.out.println("userDto = " + userDto); + } + } + + @Test + void findUserDtoAlias() { + QMember memberSub = new QMember("memberSub"); + List result = queryFactory + .select(Projections.fields(UserDto.class, + member.username.as("name"), + ExpressionUtils.as(JPAExpressions + .select(memberSub.age.max()) + .from(memberSub), "age") + )) + .from(member) + .fetch(); + + for (UserDto userDto : result) { + System.out.println("userDto = " + userDto); + } + } + + @Test + void findDtoByQueryProjection() { + List result = queryFactory + .select(new QMemberDto(member.username, member.age)) + .from(member) + .fetch(); + + for (MemberDto memberDto : result) { + System.out.println("memberDto = " + memberDto); + } + } + + @Test + void dynamicQuery_booleanBuilder() { + String usernameParam = "member1"; + Integer ageParam = 10; + + List result = searchMember1(usernameParam, ageParam); + assertThat(result.size()).isEqualTo(1); + } + + private List 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 + void dynamicQuery_WhereParam() { + String usernameParam = "member1"; + Integer ageParam = null; + + List result = searchMember2(usernameParam, ageParam); + assertThat(result.size()).isEqualTo(1); + } + + private List searchMember2(String usernameCond, Integer ageCond) { + + return queryFactory + .selectFrom(member) + .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 + void bulkUpdate() { + + // bulk update 는 영속성 컨텍스트에는 값이 변하지 않고 남아있다. + // 변경하고 DB에서 다시 조회를 하더라도 영속성 컨텍스트에 이미 값이 있기 때문에 + // 영속성 컨텍스트의 값이 우선권을 가진다. + long count = queryFactory + .update(member) + .set(member.username, "비회원") + .where(member.age.lt(28)) + .execute(); + + List result = queryFactory + .selectFrom(member) + .fetch(); + + for (Member member1 : result) { + System.out.println("member1 = " + member1); + } + + // 벌크 연산 후에는 초기화를 하는 것이 좋다. + em.flush(); + em.clear(); + + result = queryFactory + .selectFrom(member) + .fetch(); + + for (Member member1 : result) { + System.out.println("member1 = " + member1); + } + } + + @Test + void bulkAdd() { + long cnt = queryFactory + .update(member) + .set(member.age, member.age.add(1)) + .execute(); + em.flush(); + em.clear(); + List result = queryFactory + .selectFrom(member) + .fetch(); + + for (Member member1 : result) { + System.out.println("member1 = " + member1); + } + } + + @Test + void bulkDelete() { + long cnt = queryFactory + .delete(member) + .where(member.age.gt(18)) + .execute(); + + em.flush(); + em.clear(); + List result = queryFactory + .selectFrom(member) + .fetch(); + + for (Member member1 : result) { + System.out.println("member1 = " + member1); + } + } + + @Test + void sqlFunction() { + List 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 + void sqlFunction2() { + List 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); + } + } }