select_문 :: =
select_절
from_절
[where_절]
[groupby)절]
[having_절]
[orderby_절]
update_문 :: = update_절 [where_절]
delete_문 :: = delete_절 [where_절]
참고로 엔티티를 저장할 때에넌 persist()
메소드를 사용하면 되므로 INSERT문은 없다
기본문법과 쿼리API
SELECT문
SELECT m FROM Member AS m where m.username = 'Hello'
대소문자 구분
엔티티와 속성은 대소문자를 구분한다. 예를 들어 Member, username은 대소문자를 구분한다
반면에 SELECT, FROM, AS같은 JPQL키워드는 대소문자를 구분하지 않는다.
엔티티이름
JPQL에서 사용한 Member는 클래스 명이 아니라 엔티티 명이다. 엔티티 명은
@Entity(name=”XXX”)로도 지정할 수 있다. 엔티티 명을 지정하지 않으면 클래스명을 기본값으로 사용한다.
별칭은 필수
Member AS m 을 보면 Member에 m 이라는 별칭을 주었따. 별칭을 필수로 사용해야한다.
별칭이 없으면 잘못된 문법이라는 오류가 발생한다. (별칭 줄 때 AS는 생략가능)
TypeQuery, Query
JPQL을 실행하려면 쿼리 객체를 만들어야 한다. 쿼리 객체는 반환할 타입을 명확하게 지정할 수 있으면 TypeQuery
를 사용하고, 반환 타입을 명확하게 지정할 수 없으면 Query
객체를 사용하면 된다.
//TypeQuery 사용
TypedQuery<Member> query = em.createQuery("SELECT m FROM Member m",Member.class);
List<Member> resultList = query.getResultList();
for(Member member : resultList){
System.out.println("Member = " + member);
}
//Qeury사용해야할때
Query query = em.createQuery("SELECT m.username, m.age from Member m");
List resultList = query.getResultList();
for(Object o : resultList){
Object[] result = (Object[])o; //결과가 둘이 이상이면 Object[] 반환
System.out.println("username = " + result[0]);
System.out.println("age = " + result[1]);
}
조회대상이 Query를 사용할 코드는 String
타입과 Integer
타입이므로 조회 대상 타입이 명확하지 않다. 이럴땐 Query객체를 사용해야 한다.
파라미터 바인딩
JDBC는 위치기준 파라미터 바인딩만 지원하지만 JPQL은 이름 기준 파라미터 바인딩도 지원한다
이름 기준 파라미터
파라미터를 이름으로 구분하는 방법이다.
String usernameParam = "User1";
TypedQuery<Member> query =
em.createQuery("SELECT m FROM Member m where m.username = :username",Member.class);
query.setParameter("username",usernameParam);
List<Member> resultList = query.getResultList();
:username
으로 이름기준 파라미터를 정의하고 query.setParameger()
에서 username
이라는 이름으로 파라미터를 바인딩한다.
위치 기준 파라미터
//이렇게 연속해서 메소드체인방식으로 작성도 가능
List<Member> members =
em.createQuery("SELECT m FROM Member m where m.username = ?1", Member.class)
.setParameger(1,usernameParam)
.getResultList();
파라미터 바인딩은 필수!
성능이슈와 보안적인 이슈로 파라미터 바인딩은 필수이다.
먼저 성능 면에서 JPA는 파라미터 값이 달라도 같은 쿼리로 인식해서 JPQL을 SQL로 파싱한 결과를 재사용할 수 있다.
따라서 성능면에서 더 우수하다.
그리고 파라미터 바인딩 방식을 사용하지 않고 직접 문자를 더해 만들면 악의적인 사용자에 의해 SQL인젝션 공격을 당할 수 있다.