JPAQuery
QueryDSL을 사용하기 위한 객체로 엔티티 매니저를 통해 생성 @PersistenceContext
EntityManager entityManager;
@Test
void queryDslTest(){
JPAQuery<Product> query = new JPAQuery(entityManager);
QProduct qProduct = QProduct.product;
List<Product> productList = query
.from(qProduct)
.where(qProduct.name.eq("펜"))
.orderBy(qProduct.price.asc())
.fetch();
for(Product product : productList){
System.out.println("-----------------------");
System.out.println();
System.out.println("Product Number : " + product.getNumber());
System.out.println("Product Name : " + product.getName());
System.out.println("Product Price : " + product.getPrice());
System.out.println("Product Stock : " + product.getStock());
System.out.println("-----------------------");
}
}
다음과 같이 select 절 부터 작성이 가능하다.
void queryDslTest2(){
JPAQueryFactory jpaQueryFactory = new JPAQueryFactory(entityManager);
QProduct qProduct = QProduct.product;
List<String> productList = jpaQueryFactory.select(qProduct.name)
.from(qProduct)
.where(qProduct.name.eq("펜"))
.orderBy(qProduct.price.asc())
.fetch();
for(String product : productList){
System.out.println("-----------------------");
System.out.println();
System.out.println("Product Name : " + product);
System.out.println("-----------------------");
}
}
/** 2개 이상을 조회할 시에는 Tuple 타입을 통해 리스트에 넣어준다. */
List<Tuple> tupleList = jpaQueryFactory
.select(qProduct.name, qProduct.price)
.from(qProduct)
.where(qProduct.name.eq("펜"))
.orderBy(qProduct.price.asc())
.fetch();
for(Tuple tuple : tupleList){
System.out.println("-----------------------");
System.out.println("Product name : " + tuple.get(qProduct.name));
System.out.println("Product name : " + tuple.get(qProduct.price));
System.out.println("-----------------------");
}
@Configuration
public class QueryDSLConfiguration {
/** 엔티티 매니저 주입을 위한 어노테이션 */
@PersistenceContext
EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory(){
return new JPAQueryFactory(entityManager);
}
}
JPAQueryFactory 객체를 Bean으로 등록하면 초기화하지 않고 스프링 컨테이너에서 가져다 쓸 수 있다.
QuerydslPredicateExecutor, QuerydslRepositorySupport
JpaRepository와 함께 리포지토리에서 QueryDSL을 사용할 수 있게 인터페이스 제공
public interface QProductRepository extends JpaRepository<Product, Long>, QuerydslPredicateExecutor<Product> {
}
@SpringBootTest
public class QProductRepositoryTest {
@Autowired
QProductRepository qProductRepository;
@Test
public void queryDSLTEST1(){
Predicate predicate = QProduct.product.name.containsIgnoreCase("펜").and(QProduct.product.price.between(1000,2500));
Optional<Product> foundProduct = qProductRepository.findOne(predicate);
if(foundProduct.isPresent()){
Product product = foundProduct.get();
System.out.println(product.getNumber());
System.out.println(product.getName());
System.out.println(product.getPrice());
System.out.println(product.getStock());
}
}
}
@Test
public void queryDSLTEST2(){
QProduct qProduct = QProduct.product;
/** predicate 객체 선언하지 않고 그대로 서술부만 가져다가 사용*/
Iterable<Product> productList = qProductRepository.findAll(
qProduct.name.contains("펜")
.and(qProduct.price.between(550,1500))
);
for(Product product : productList){
System.out.println(product.getNumber());
System.out.println(product.getName());
System.out.println(product.getPrice());
System.out.println(product.getStock());
}
}
Predicate
간단하게 표현식으로 정의한 쿼리
contains
해당 이름 포함 시
containsIgnoreCase
해당 이름 포함 시(대소문자 구분 X)
and
조건 추가
Optional<T> findOne(Predicate)
1개 찾기
Iterable<T> findAll(Predicate)
여러 개 찾기(List, Page 등등)
QueryDSL을 간편하게 사용할 수 있게 하지만 Join, Fetch를 사용할 수 없다.
CustomRepository를 활용해 리포지토리를 구현하는 방식으로 QueryDSL을 사용할 수 있게한다.
ProductRepository : JpaRepository, ProductRepositoryCustom 상속받음
ProductRepositoryCustom : QueryDslRepositorySupport 상속받음
QueryDslRepositorySupport : QueryDSL을 사용하기 위한 인터페이스
public interface ProductRepositoryCustom {
/** 구현하고자하는 메서드 정의 */
List<Product> findByName(String name);
}
public class ProductRepositoryCustomImpl extends QuerydslRepositorySupport implements ProductRepositoryCustom {
/** QuerydslRepositorySupport, ProductRepositoryCustom 상속 받아 QueryDSL 사용과 구현할 메소드 받아옴*/
public ProductRepositoryCustomImpl(){
super(Product.class);
}
@Override
public List<Product> findByName(String name) {
QProduct product = QProduct.product;
List<Product> productList = from(product)
.where(product.name.eq(name))
.select(product)
.fetch();
return productList;
}
}
@Repository
public interface ProductRepository extends JpaRepository<Product,Long>, ProductRepositoryCustom {
}
@Autowired
ProductRepository productRepository;
@Test
void findByNameTest(){
List<Product> productList = productRepository.findByName("펜");
for(Product product : productList){
System.out.println(product.getNumber());
System.out.println(product.getName());
System.out.println(product.getPrice());
System.out.println(product.getStock());
}
}