JAVA ORM - JPA(JPQL)
JPQL(Java Persistencce Query Language)
JPA에서 제공하는 쿼리언어.SQL과 유사하지만, 테이블이 아닌 엔티티 객체를 대상으로 쿼리를 작성한다.
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
...
}
이 멤버라는 엔티티에 대해 쿼리를 작성한다 치자.
EntityManager em = entityManagerFactory.createEntityManager();
TypedQuery<Member> query = em.createQuery("SELECT m FROM Member m", Member.class);
List<Member> members = query.getResultList();
main문에 이런식으로 쿼리를 작성할 수 있다.
하지만, 쿼리의 조건이 바뀌거나 할때 동적쿼리를 작성해야하는데 이 때 사용되는게 Criteria API 이다.
Criteria API 를 사용하기위해
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaBuilder객체를 먼저 생성해준다.
CriteriaQuery<Member> query = cb.createQuery(Member.class);
Root<Member> m = query.from(Member.class);
CriteriaQuery<Member> cq = query.select(m).where(cb.equal(m.get("username"), "kim"));
List<Member resulstList = em.createQuery(cq).getResultList();
그다음 쿼리를 작성해주고 경과를 넣어준다.
이런방식으로 쿼리를 짠다면, 동적쿼리를 짜기에 좋다.
하지만 크리테리아는 sql같지도않고 너무 어렵다.
대체제로 QueryDSL을 사용한다.
QueryDSL
크리테리아 대체제로 동적쿼리 작성에 이점이 있고, 자바코드로 JPQL을 작성할 수 있고, 컴파일시점에 오류를 잡을 수 있다는 장점이 있다.
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QMember qMember = QMember.member;
String nameParam = "John";
Integer ageParam = 25;
List<Member> members = queryFactory.selectFrom(qMember)
.where(nameEq(nameParam), ageGt(ageParam))
.fetch();
확실히 크리테리아 보다 훨씬 가독성도 좋고 사용하기에도 편한게 보인다.
이걸 알기전에는 꼭 JPQL을 알고하면 좋다.
Native SQL
em.createNatvieQuery(쿼리문).getResultList(); 하면 쿼리문 자리에 생 쿼리를 넣어도 잘 작동한다.
문법
엔티티와 속성은 대소문자구분O, 키워드는 구분X, 엔티티이름 사용함. 테이블이름X, 별칭은 필수
TypeQuery : 반환 타입이 명확할 때.
Query : 반환타입이 불분명할 때.
TypedQuery<Member> query1 = em.createQuery("select m from Member m", Member.class);
Query query2 = em.createQuery("select m.username, m.age from Member m");
결과조회
query.getResultList(): 결과가 여러개일 때.
query.getSingleResult(): 결과가 하나일 때.
TypedQuery<Member> query1 = em.createQuery("select m from Member m", Member.class);
List<Member> resultList = query.getResultList(); // 결과없으면 빈 리스트반환
TypedQuery<Member> query1 = em.createQuery("select m from Member m where m.id = 1", Member.class);
Member result = query.getSingleResult(); // 결과없으면예외, 두개이상이면 예외.
페이징
setFirstResult(int startPosition) : 조회 시작위치
setMaxResulst(int maxResult) : 조회할 데이터수
List<Member > result = em.createQuery("select m from Member m order by m.age desc", Member.class)
.setFirstResult(10)
.setMaxResults(20)
.getResultList();
서브쿼리는
WHERE, HAVING, SELECT절에서만 사용 가능. FROM절의 서브쿼리는 불가능