Spring/QueryDSL
JPQL vs Querydsl
느리지만 꾸준하게
2022. 4. 19. 22:56
Querydsl 기본문법을 보자.
// QuerydslBasicTest
// JPQL 먼저 작성
@Test
public void startJPQL() {
// member1을 찾아라.
Member findMember = em.createQuery("select m from Member m where m.username = :username", Member.class)
.setParameter("username", "member1")
.getSingleResult();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
돌리면 쿼리가 잘 동작한다.
select
member0_.id as id1_1_,
member0_.age as age2_1_,
member0_.team_id as team_id4_1_,
member0_.username as username3_1_
from
member member0_
where
member0_.username=?
아래와 같이 startQuerydsl 작성하고 compileQuerydsl 돌려주면 QMember과 QTeam이 생긴다.
// QuerydslBasicTest
package study.querydsl.entity;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.aspectj.lang.annotation.Before;
import org.assertj.core.api.Assertions;
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.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import static org.assertj.core.api.Assertions.*;
@SpringBootTest
@Transactional
public class QuerydslBasicTest {
@Autowired
EntityManager em;
// 각 테스트 실행전에 데이터를 세팅을 하고 들어간다.
@BeforeEach
public void before() {
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 30, teamB);
Member member4 = new Member("member4", 40, teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
}
// JPQL 먼저 작성
@Test
public void startJPQL() {
// member1을 찾아라.
String qlString =
"select m from Member m " +
"where m.username = :username";
Member findMember = em.createQuery(qlString, Member.class)
.setParameter("username", "member1")
.getSingleResult();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
@Test
public void startQuerydsl() {
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
}
}
test에 startQuerydsl을 작성하고 실행해도 잘 동작되는 것을 볼 수 있다.
@Test
public void startQuerydsl() {
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
// 어떤 Q 멤버인지 이름을 주는 것
QMember m = new QMember("m");
Member findMember = queryFactory
.select(m)
.from(m)
.where(m.username.eq("member1"))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
select
member0_.id as id1_1_,
member0_.age as age2_1_,
member0_.team_id as team_id4_1_,
member0_.username as username3_1_
from
member member0_
where
member0_.username=?
startJQPL과 startQuerydsl 두개의 큰 차이가 있다.
startJQPL은 문자형식으로 작성되어 아래와 같이 에러가 있을 때
사용자가 실행을 했을 때 메서드가 호출이 되면 에러가 있는것을 뒤늦게 발견한다. 즉 런타임 오류가 발생하는 것이다.
// JPQL 먼저 작성
@Test
public void startJPQL() {
// member1을 찾아라.
// JPQL에서는 parameter 바인딩을 해주고
String qlString =
"select m from Member m " +
"where m.usernameㄸㄸ = :username";
Member findMember = em.createQuery(qlString, Member.class)
.setParameter("username", "member1")
.getSingleResult();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
startQuerydsl은 에러가 컴파일 타임때 바로 알아차릴 수가 있다.
두 가지의 장점이 있는 것이다.
- 파라미터 바인딩을 자동으로 해결해준다.
- 컴파일 시점때 에러를 잡아준다.
@Test
public void startQuerydsl() {
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
// 어떤 Q 멤버인지 이름을 주는 것
QMember m = new QMember("m");
// JPQL과 똑같다.
Member findMember = queryFactory
.select(m)
.from(m)
// 파라미터 바인딩을 안해도 eq를 해서 자동으로 JDBC의 prepare stament로 파라미터로 바인딩을 자동으로 한다.
.where(m.usernameㄸㄷ.eq("member1"))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
그리고 QuerydslBasicTest에서 아래 부분을 필드로 뺄 수가 있다.
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
package study.querydsl.entity;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.aspectj.lang.annotation.Before;
import org.assertj.core.api.Assertions;
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.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import static org.assertj.core.api.Assertions.*;
@SpringBootTest
@Transactional
public class QuerydslBasicTest {
@Autowired
EntityManager em;
JPAQueryFactory queryFactory;
// 각 테스트 실행전에 데이터를 세팅을 하고 들어간다.
@BeforeEach
public void before() {
// 필드레벨로 가져가도 괜찮다.
// spring framework가 주입해주는 엔티티 자체가 멀티스레드에 문제없이 설계가 되어있다.
// 여러 멀티스레드가 걸랴와도 현재 트랜잭션이 어디에 걸려있는지에 따라서 트랜잭션에 바인딩 되도록 다 분배를 해준다.
// 즉 동시성 문제가 없다.
queryFactory = new JPAQueryFactory(em);
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 30, teamB);
Member member4 = new Member("member4", 40, teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
}
// JPQL 먼저 작성
@Test
public void startJPQL() {
// member1을 찾아라.
// JPQL에서는 parameter 바인딩을 해주고
String qlString =
"select m from Member m " +
"where m.username = :username";
Member findMember = em.createQuery(qlString, Member.class)
.setParameter("username", "member1")
.getSingleResult();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
@Test
public void startQuerydsl() {
// 어떤 Q 멤버인지 이름을 주는 것
QMember m = new QMember("m");
// JPQL과 똑같다.
Member findMember = queryFactory
.select(m)
.from(m)
// 파라미터 바인딩을 안해도 eq를 해서 자동으로 JDBC의 prepare stament로 파라미터로 바인딩을 자동으로 한다.
.where(m.username.eq("member1")) // 파라미터 바인딩 처리
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
}
<출처 김영한: 실전! Querydsl >
https://www.inflearn.com/course/Querydsl-%EC%8B%A4%EC%A0%84/dashboard
실전! Querydsl - 인프런 | 강의
Querydsl의 기초부터 실무 활용까지, 한번에 해결해보세요!, - 강의 소개 | 인프런...
www.inflearn.com