Spring Data JPA를 이용하면, 리포지토리에 JpaRepository를 상속하여 다양한 CRUD 메소드를 사용할 수 있음
하지만 JpaRepository의 기능만으로는 실무의 모든 기능을 구현할 수 없기 때문에 로직에 맞는 함수를 따로 정의해줘야 하며, 이때 쿼리 메소드를 사용함
메소드 이름만으로 쿼리를 작성할 수 있음
"주제" + By + "서술어"
public interface BoardRepository extends CrudRepository<Board, Long> {
// Board 엔티티에서 title 변수 값만 조회
List<Board> findByTitle(String searchKeyword);
}
// 추가된 메소드를 테스트
@SpringBootTest
public class QueryMethodTest {
@Autowired
private BoardRepository boardRepo;
@BeforeEach
public void dataPrepare() {
for (int i = 1; i <= 200; i++) {
Board board = new Board();
board.setTitle("테스트 제목 " + i);
board.setWriter("테스터");
board.setContent("테스트 내용 " + i);
board.setCreateDate(new Date());
board.setCnt(0L);
boardRepo.save(board);
}
}
@Test
public void testFindByTitle(){
List<Board> boardList = boardRepo.findByTitle("테스트 제목 10");
System.out.println("검색 결과");
for (Board board : boardList) {
System.out.println("---> " + board.toString());
}
}
}
쿼리 메소드를 통해 간단하게 필요한 객체를 조회할 수 있지만, 조금 더 복잡한 조건을 사용하려면 메소드의 길이가 증가하게 된다는 단점이 있음
이러한 단점을 해결하기 위해 JPQL을 사용함
JPA Query Language, JPA에서 사용할 수 있는 쿼리
복잡한 조건을 메소드로 표현하기 어려울 수 있기 때문에, JPQL을 사용하여 직접 쿼리문을 작성해 객체를 조회할 수 있음
객체를 대상으로 하는 쿼리문이며 SQL을 추상화해서 사용하기 때문에, 어떤 DB를 사용하더라도 문제없이 사용할 수 있음
@Query("쿼리문")으로 사용함
@Query("SELECT p FROM Product p WHERE p.name = :name")
List<Product> findByNameParam(@Param("name") String name);
// :name은 @Param("name")을 사용해서 넣어줄 수 있음
하지만 직접 문자열로 쿼리를 입력하기 때문에, 컴파일 시점에 에러를 잡지 못하고 런타임 에러가 발생할 수 있다는 단점이 있음
이러한 단점을 해결하기 위해 QueryDSL을 사용함
쿼리문을 소스코드를 사용해서 작성함
❓ QClass
QueryDSL은 컴파일 단계에서 엔티티를 기반으로 QClass를 생성하는데, JPAAnnotationProcessor가 컴파일 시점에 작동해서 @Entity 등의 어노테이션을 찾아 해당 파일을 분석해서 QClass를 만듦QClass는 Entity와 형태가 똑같은 Static Class로, QueryDSL은 쿼리를 작성할 때 QClass를 기반으로 쿼리를 실행함
@PersistenceContext
EntityManager entityManager;
@Test
void queryDslTest() {
// QueryDSL을 사용하기 위해서는 JPAQuery 객체를 사용함
// JPAQuery는 엔티티 매니저를 활용해 생성함
JPAQuery<Product> query = new JPAQuery(entityManager);
QProduct qProduct = QProduct.product;
// 빌더 형식으로 쿼리를 작성함
// List 타입으로 값을 리턴받기 위해서는 fetch()를 사용해야 함
List<Product> productList = query
.from(qProduct)
.where(qProduct.name.eq("펜"))
.orderBy(qProduct.price.asc())
.fetch();
for (Product product : productList) {
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());
}
}
도서 '스프링부트 핵심 가이드'
https://binco.tistory.com/entry/Spring-Data-JPA-%EC%BF%BC%EB%A6%AC%EB%A9%94%EC%84%9C%EB%93%9C?category=1036292
https://velog.io/@simgyuhwan/%EC%BF%BC%EB%A6%AC-%EB%A9%94%EC%86%8C%EB%93%9C-JPQL-Querydsl-%EC%9A%94%EC%95%BD
https://yeoncoding.tistory.com/369