김영한 님의 스프링 DB 2편 - 데이터 접근 활용 기술 강의를 보고 작성한 내용입니다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-2/dashboard
"select * from item" + "where ..." 처럼 +
로 합치는데 공백이 없으면 오류 발생
Query는 문자이기 때문에 Type-check 불가능, 실행하기 전까지 작동 여부 확인 불가능
DSL = Domain( 도메인 ) Specific( 특화 ) Language( 언어 )
QueryDSL : 쿼리에 특화된 프로그래밍 언어
QueryDSL은 쿼리를 자바로 type-safe 하게 개발할 수 있도록 지원하는 프레임워크
컴파일 시 에러 체크가 가능하고 주로 JPA 쿼리( JPQL )에 사용
데이터 쿼리 기능을 추상화
QueryDSL로 작성하면 JPQL이 생성되고 SQL이 실행된다
implementation 'com.querydsl:querydsl-jpa'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
// Querydsl 추가, 자동 생성된 Q클래스 gradle clean으로 제거
clean {
delete file('src/main/generated')
}
gradle clean
명령어를 실행할 때 src/main/generated
의 파일도 함께 삭제해준다
인텔리제이는 직접 삭제해야한다
엔티티를 QueryDSL 에서 사용하기 위한 Q 타입을 생성해야한다
build 방식이 InetelliJ 인 경우
build ➜ Bjild Project
를 하면 src/main/generated
하위에 생성된다build 방식이 gradle 인 경우
Gradle ➜ Tasks ➜ build ➜ clean
: gradle 설정 초기화 ( build 폴더가 삭제됨 )
Gradle ➜ Tasks ➜ other ➜ compileJava
: Q 타입 생성
build ➜ generated ➜ sources ➜ annotationProcessor ➜ java/main
하위에 Q 타입이 생성된다
public class JpaItemRepositoryV3 implements ItemRepository {
private final EntityManager em;
private final JPAQueryFactory query;
public JpaItemRepositoryV3(EntityManager em) {
this.em = em;
this.query = new JPAQueryFactory(em);
}
...
}
Querydsl을 사용하려면 JPAQueryFactory
가 필요
JPAQueryFactory
는 JPA 쿼리인 JPQL을 만들어주는 빌더 역할을 하기 때문에 EntityManager
가 필요
QItem item = QItem.item;
List<Item> result = query
.select(item)
.from(item)
.where(builder)
.fetch();
QItem item = new QItem("i");
으로 사용한다
QItem 내부에 QItem.item
이 있기 때문에 QItem을 static import 해서 item
으로 사용할 수 있다
코드에서 사용한 방식은 위의 2개를 합친 방식 ( QItem 선언 + QItem.item )
BooleanBuilder builder = new BooleanBuilder();
if (StringUtils.hasText(itemName)) {
builder.and(item.itemName.like("%" + itemName + "%"));
}
if (maxPrice != null) {
builder.and(item.price.loe(maxPrice));
}
List<Item> result = query
.select(item)
.from(item)
.where(builder)
.fetch();
BooleanBuilder
를 사용해서 원하는 where 조건들을 넣어주면 된다public List<Item> findAll(ItemSearchCond cond) {
String itemName = cond.getItemName();
Integer maxPrice = cond.getMaxPrice();
QItem item = QItem.item;
return query
.select(item)
.from(item)
.where(likeItemName(itemName), maxPrice(maxPrice))
.fetch();
}
private BooleanExpression likeItemName(String itemName) {
if (StringUtils.hasText(itemName)) {
return item.itemName.like("%" + itemName + "%");
}
return null;
}
private BooleanExpression maxPrice(Integer maxPrice) {
if (maxPrice != null) {
return item.price.loe(maxPrice);
}
return null;
}
where 에 조건을 직접 넣는 경우 AND 조건으로 처리된다
다른 쿼리를 작성할 때 위의 두 조건 메서드를 재사용할 수 있다
QueryDSL 은 별도의 스프링 예외 추상화를 지원하지 않는다
대신 @Repository
에서 스프링 예외 추상화를 처리해준다
3-1번의 JpaItemRepositoryV3
는 JPA 방식을 사용 ( not SpringDataJPA )