728x90
- Spring 3.X 버전 연동 설정
dependencies {
....
// 9. QueryDSL 적용을 위한 의존성 (SpringBoot3.0 부터는 jakarta 사용해야함)
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}
QueryDSL
- Entity의 매핑정보를 활용하여 쿼리에 적합하도록 쿼리 전용 클래스(Q클래스)로 재구성해주는 기술
장점
- 문자가 아닌 코드로 쿼리를 작성함으로써, 컴파일 시점에 문법 오류를 쉽게 확인할 수 있다.
- 자동 완성 등 IDE의 도움을 받을 수 있다.
- 동적인 쿼리 작성이 편리하다.
- 쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있다.
1. QueryDslPredicateExecutor 사용
원리
- QueryDSL 의존성을 추가하면 SpringData에 의해 QueryDslPredicateExecutor 인터페이스가 추가된다.
- QueryDslPredicateExecutor 인터페이스는 Repository가 QueryDsl 을 실행할 수 있는 인터페이스를 제공하는 역할을 합니다.
기능
- QueryDSL의 Predicate 인터페이스로 조건문을 여러개를 구성하여 따로 관리할 수 있다.
- findOne(Predicate), findAll(Predicate) 주로 이 2개 메소드가 사용된다.
- findOne = Optional<T> 리턴
- findAll = List<T> | Page<T> | Iterable<T> | Slice<T> 리턴
- QuerydslPredicateExecutor 활용: Join 연산이 불가능, 대신 조건이 많은 쿼리가 가능
- 멤버 컬렉션까지만 조회 가능하며 이를 묵시적 조인(1 Depth 자동 조인)이라고 한다.
- 반면에, Join 연산이 수행되는 건 명시적 조인(2 Depth 이상 조인)이라고 한다.
- 따라서 JPQL과 JPAQueryFactory로 join 연산하는 법을 배움
실습
- Q 클래스(쿼리타입)
- QueryDSL로 쿼리를 작성할 때 Q클래스를 사용함으로써 쿼리를 Type-Safe하게 작성 가능
- 기본 인스턴스를 사용하면 import static을 활용해서 코드를 더 간결하게 작성 가능
- 사용할 Repository에서 QueryDslPredicateExecutor를 상속받는다.
public interface ItemRepository extends JpaRepository<Item, Long>,
QuerydslPredicateExecutor<Item> {
}
- QueryDSL 사용 예제
QItem item = QItem.item;
Iterable<Item> result = itemRepository.findAll(
item.name.contains("장난감").and(item.price.between(10000, 20000))
);
2. JPAQueryFactory 사용
- JPAQueryFactory: 재구성한 Q클래스를 통해 문자열이 아닌 객체 또는 함수로 쿼리를 작성하고 실행하게 해주는 기술
- JPAQueryFactory에 entityManager를 주입해 Bean으로 등록해줘야 함
@Configuration
public class JPAConfiguration {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
사용 예제
public List<User> selectUserByUsernameAndPassword(String username, String password){
QUser user = QUser.user;
List<Person> userList = jpaQueryFactory
.selectFrom(user)
.where(person.username.eq(username)
.and(person.password.eq(password))
.fetch();
return userList;
}
JPQL(Java Persistence Query Language)
- Table이 아닌 Entity(객체) 기준으로 작성하는 쿼리
- 이를 사용할 수 있도록 Entitymanager 또는 @Query 구현체를 통해 JPQL 쿼리를 사용할 수 있음
1. EntityManager.createQuery()
@Test
public void testEmCreateQuery() {
String qlString = "select u from User u " +
"where u.username = :username";
Member findUser = em.createQuery(qlString, User.class)
.setParameter("username", "teasun")
.getSingleResult();
assertThat(findUser.getUsername()).isEqualTo("teasun");
}
2. @Query (repository interface)
- ?변수순번 사용
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u, u.password AS customField FROM User u WHERE u.username = ?1")
List<User> findByUsernameWithCustomField(String username, Sort sort);
@Query("SELECT u FROM User u WHERE u.username = ?1")
List<User> findByUsername(String username, Sort sort);
}
- :변수명 사용
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u, u.password AS customField FROM User u WHERE u.username = :username")
List<User> findByUsernameWithCustomField(String username, Sort sort);
@Query("SELECT u FROM User u WHERE u.username = :username")
List<User> findByUsername(String username, Sort sort);
}
'TIL' 카테고리의 다른 글
[231227] 이메일 인증 구현 (링크 방식) (0) | 2023.12.27 |
---|---|
[231221] update 시 Timestamp 값으로 null이 반환 (0) | 2023.12.21 |
[231218] 이진트리, 힙 (0) | 2023.12.18 |
[231213] MySQL 공부 (0) | 2023.12.13 |
[231211] Spring 심화 개인 과제 피드백 (0) | 2023.12.11 |