(Java Persistence Query Language)
Table 이 아닌 Entity(객체) 기준으로 작성하는 쿼리
EntityManger
또는 @Query
구현체를 통해 JPQL 쿼리를 사용할 수 있다.@Test
public void testEmCreateQuery() {
String qlString = "select u from User u " +
"where u.username = :username";
Member findUser = em.createQuery(qlString, User.class)
.setParameter("username", "찾을 username")
.getSingleResult();
assertThat(findUser.getUsername()).isEqualTo("찾을 username");
}
!!코드에 문자열이 들어가는게 안 좋은 이유 !!
1. 문자열은 오타가 발생할 여지가 많다.
2. 개발할때 같은 공통적인 문자열이 있을때 한군데에서 수정이 일어나면 모두 수정해야한다.
3. 잘못된 코드가 있더라도 문자열 자체를 컴파일러가 검사 하지는 않기 때문에 컴파일 시점에 잡지못한다.
4. 이로인해 버그가 있더라도 메소드를 실행하는 시점인 런타임시점에 버그가 발생한다.
5. 런타임 시점에 발생한 버그는 서비스 정합성에 영향을 주며 원인을 찾기도 어렵다.
=> String이기 때문에 오타가 있어도 실행되어서 db에 접근하기 전까지는 프로그램이 오류를 찾을 수가 없다. (프로그램 입장에서는 오류가 아니니까)
해결방법
@Query
의 인자값으로 간단하게 쿼리를 작성
방법
?변수순번 사용
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);
}
:변수명 사용
예시 - from에 Entity의 객체를 선언, 해당 객체의 속성으로 조건과 파라미터를 작성
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);
}
Entity 의 매핑정보를 활용하여 쿼리에 적합하도록 쿼리 전용 클래스(Q클래스)로 재구성해주는 기술
여기에 JPAQueryFactory 을 통한 Q클래스를 활용할 수 있는 기능들을 제공한다.
JPAQueryFactory
예시 -> JPAQueryFactory에 EntityManager를 주입해서 인스턴스를 생성해야한다.
@PersistenceContext
EntityManager em;
public List<User> selectUserByUsernameAndPassword(String username, String password){
JPAQueryFactory jqf = new JPAQueryFactory(em);
QUser user = QUser.user;
List<Person> userList = jpf
.selectFrom(user)
.where(person.username.eq(username)
.and(person.password.eq(password))
.fetch();
return userList;
}
JPAQueryFactory 사용을 위해 추가해야할 코드
JPAQueryFactory 에 entityManager 를 주입해서 Bean 으로 등록
-> 따로 계속 등록해줄 필요 없도록
// configuration 패키지안에 추가
@Configuration
public class JPAConfiguration {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}