- JPQL vs Querydsl
@SpringBootTest
@Transactional
public class QuerydslBasicTest {
@Autowired
EntityManager em;
JPAQueryFactory queryFactory;
@BeforeEach
public void before() {
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);
}
@Test
public void startJPQL() {
//member1을 찾아라
String qlString = "select m from Member m " +
"where 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); 얘는 필드로 가져갈 수 있다.
// QMember m = new QMember("m"); // 첫번째
// QMember m = QMember.member; // 두번째
// Member findMember = queryFactory
// .select(m)
// .from(m)
// .where(m.username.eq("member1")) //파라미터 바인딩 처리
// .fetchOne();
Member findMember = queryFactory
.select(member)
.from(member)
.where(member.username.eq("member1")) //파라미터 바인딩 처리
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
@Test
public void search() {
Member findMember = queryFactory
.selectFrom(member)
.where(member.username.eq("member1")
.and(member.age.eq(10)))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
assertThat(findMember.getAge()).isEqualTo(10);
}
@Test
public void searchAndParam() { // ,로 이어나가면 전부 and로 연결된다.
Member findMember = queryFactory
.selectFrom(member)
.where(
member.username.eq("member1"),
(member.age.eq(10)))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
assertThat(findMember.getAge()).isEqualTo(10);
}
}
@SpringBootTest
@Transactional
public class QuerydslBasicTest {
@Autowired
EntityManager em;
JPAQueryFactory queryFactory;
@BeforeEach
public void before() {
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);
}
- Querydsl은 JPQL을 빌드하는 역활을 하기 떄문에 EntityManager를 통해 실행된다.
- Querydsl을 사용하기 위해선 JPAQueryFactory객체를 사용해야 하고, EntityManager를 파라미터로 넣어준다.
- @BeforeEach를 통해 테스트 메서드가 실행되기 이전에 공통으로 mamber 엔티티를 생성한다.
- JPQL Test 코드
@Test
public void startJPQL() {
//member1을 찾아라
String qlString = "select m from Member m " +
"where username = :username";
Member findMember = em.createQuery(qlString, Member.class)
.setParameter("username", "member1")
.getSingleResult();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
- em.createQuery를 통해 JPQL를 사용하여 동적 쿼리를 작성하는 방법이다.
- 파라미터 바인딩 방식으로 username에 member1에 해당하는 엔티티를 찾아오는 쿼리이다.
- Querydsl
- Querydsl
@Test
public void startQuerydsl() {
//member1을 찾아라.
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QMember m = new QMember("m");
Member findMember = queryFactory
.select(m)
.from(m)
.where(m.username.eq("member1"))//파라미터 바인딩 처리
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
- 가장 기본적인 Querydsl을 사용한 방식이다.
- JPAQueryFactory에 EntityManager를 파라미터로 넘겨 객체를 생성한다.
- new QMember를 통해 Querydsl을 통해 생성된 QMember 클래스를 생성한다.
new QMember("m");
("m")
- "m"은 별칭으로 사용되는데 잘 사용하지 않는다.
- JPAQueryFactory 객체를 통해 SQL과 유사한 형태로 쿼리를 작성해주면 된다.
JPAQueryFactory queryFactory = new JPAQueryFactory(em); 얘는 필드로 가져갈 수 있다.
- 필드로 간 코드는 전체 완성된 코드를 통해 확인할 수 있다.
* JPAQueryFactory를 필드로 제공하면 동시성 문제는 어떻게 될까? 동시성 문제는 JPAQueryFactory를 생성할 때 제공하는 EntityManager(em)에 달려있다. 스프링 프레임워크는 여러 쓰레드에서 동시에 같은 EntityManager에 접근해도, 트랜잭션 마다 별도의 영속성 컨텍스트를 제공하기 때문에, 동시성 문제는 걱 정하지 않아도 된다.
- 기본 Q-Type 활용
- Q클래스 인스턴스를 사용하는 2가지 방법
QMember qMember = new QMember("m"); //별칭 직접 지정
QMember qMember = QMember.member; //기본 인스턴스 사용
- 기본 인스턴스를 static import와 함께 사용
import static study.querydsl.entity.QMember.*;
...
@Test
public void startQuerydsl3() {
//member1을 찾아라.
// QMember m = QMember.member;를 static import를 통해 생략한다.
// 기존에 static import를 하지 않으면 .select(QMember.member)와 같이 작성해줘야 한다.
Member findMember = queryFactory
.select(member)
.from(member)
.where(member.username.eq("member1"))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
- static import를 통해 member 엔티티명이 드러날 수 있도록 코드를 작성해주는 것이 좋다.
- 검색 조건 쿼리
- 기본 검색 쿼리
@Test
public void search() {
Member findMember = queryFactory
.selectFrom(member)
.where(member.username.eq("member1")
.and(member.age.eq(10)))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
assertThat(findMember.getAge()).isEqualTo(10);
}
- 검색 조건은 , and() , or()를 메서드 체인으로 연결할 수 있다.
* selectFrom은 select, From을 합친것이다.
- JPQL이 제공하는 모든 검색 조건 제공
member.username.eq("member1") // username = 'member1'
member.username.ne("member1") //username != 'member1'
member.username.eq("member1").not() // username != 'member1'
member.username.isNotNull() //이름이 is not null
member.age.in(10, 20) // age in (10,20)
member.age.notIn(10, 20) // age not in (10, 20)
member.age.between(10,30) //between 10, 30
member.age.goe(30) // age >= 30
member.age.gt(30) // age > 30
member.age.loe(30) // age <= 30
member.age.lt(30) // age < 30
member.username.like("member%") //like 검색
member.username.contains("member") // like ‘%member%’ 검색
member.username.startsWith("member") //like ‘member%’ 검색
...
- JPQL은 위와 같은 많은 메서드를 제공한다.
- AND 조건을 파라미터로 처리
@Test
public void searchAndParam() { // ,로 이어나가면 전부 and로 연결된다.
Member findMember = queryFactory
.selectFrom(member)
.where(
member.username.eq("member1"),
(member.age.eq(10)))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
assertThat(findMember.getAge()).isEqualTo(10);
}
-where()에 파라미터로 검색조건을 추가하면 AND 조건이 추가된다.
- .and를 통해 and 조건을 추가할 수 있지만
member.username.eq("member1"),
(member.age.eq(10)))
- 코드와 같이 ,를 사용하면 Querydsl이 알아서 and로 처리한다.
출처 : 인프런 - 김영한(실전! Querydsl)
'Programming > Querydsl' 카테고리의 다른 글
Querydsl - 중급 문법 (2) 동적 쿼리 (0) | 2023.07.28 |
---|---|
Querydsl - 중급 문법 (1) (프로젝션) (0) | 2023.07.28 |
Querydsl - 기본 문법 (3) (조인, 서브 쿼리, Case문, 상수, 문자 더하기) (0) | 2023.07.27 |
Querydsl - 기본 문법 (2) (결과 조회, 정렬, 페이징, 집합) (0) | 2023.07.27 |
Querydsl - Querydsl 설정 (0) | 2023.07.26 |