객체지향 쿼리 언어
JPQL
- 테이블이 아닌 엔티티 객체를 조회하는 객체지향 쿼리
- 문법은 SQL과 비슷하고, ANSI 표준 SQL이 제공하는 기능을 유사하게 지원한다.
- SQL을 추상화하여 특정 DB에 의존하지 않는다.
String jpql = "select m from Member as m where m.username = 'chae'";
List<Member> resultList = em.createQuery(jpql, Member.class).getResultList();
Criteria
- JPQL을 생성하는 빌더 역할
- 문자가 아닌 자바 코드로 JPQL을 작성한다.
- JPQL 작성시 오타가 있으면 런타임 오류가 발생하는데, Criteria는 이런 오류를 컴파일 시점에 발견할 수 있다.
- 너무 복잡하고 실용성이 없어서 QueryDSL 사용을 권장.
CriteriaBuilder cb = em.getCriteriaBuilder();
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"), "chae"));
List<Member> resultList = em.createQuery(cq).getResultList();
QueryDSL
- JPQL을 생성하는 빌더 역할
- 문자가 아닌 자바 코드로 JPQL을 작성한다.
- 컴파일 시점에 문법 오류를 발견할 수 있다.
- 단순하고 사용하기 쉬우며 동적 쿼리 작성이 편리하다.
JPAQuery query = new JPAQuery(em);
QMember member = QMember.member;
List<Member> members = query.from(member)
.where(member.username.eq("chae"))
.list(member);
네이티브 SQL
- JPA에서 제공하는 SQL을 직접 사용하는 기능
- JPQL로 해결할 수 없는 특정 DB에서만 동작하는 기능을 사용할 수 있다. ex) 오라클 CONNECT BY, 특정 DB만 사용하는 SQL 힌트
String sql = "SELECT ID, AGE, TEAM_ID, NAME FROM MEMBER WHERE NAME = 'chae'";
List<Member> resultList = em.createNativeQuery(sql, Member.class).getResultList();
JDBC 직접 사용, Mybatis 같은 SQL 매퍼 프레임워크
하이버네이트에서 JDBC 커넥션을 직접 접근하려면 JPA 구현체가 제공하는 방법을 사용해야 한다.
// 하이버네이트 JDBC 획득
Session session = em.unwrap(Session.class);
session.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
...
}
});
JDBC, Mybatis를 JPA와 함께 쓰려면 영속성 컨텍스트를 적절한 시기에 강제 플러시할 필요가 있다. JDBC, SQL 매퍼는 JPA를 우회해서 DB에 접근하기 때문에 JPA가 인지하지 못하는 문제가 발생한다. 그래서 SQL 실행 전 수동으로 플러시하여 영속성 컨텍스트 동기화가 필요하다. 스프링 프레임워크의 AOP를 통해 우회접근시 플러시하는 방식으로 해결할 수 있다.
Comments