JPA Java Persistence Query Language

What is JPQL

JPQL은 Java Persistence Query Language 의 약자로 Java의 객체지향 쿼리 언어이다.
JPQL은 데이터베이스 테이블 대신 엔티티 개체 모델을 사용하여 SQL 쿼리를 실행한다.
(👍Tip : JPA는 JPQL을 방언에 따라 적합한 데이터베이스의 SQL로 변환하는 것이다.)

Benefits of JPQL

  1. DB에 독립적이다. SQL을 추상화하여 특정 DB에 종속되지 않음.
    (oracle, mysql등 데이터베이스 방언으로 교체가능)
  2. 동적 또는 정적 쿼리가 가능하다.
  3. 조인 동작이 수행된다. (기본조인 뿐만 아니라 페치조인)
  4. update, delete로 한 번에 많은 데이터 처리가 가능하다.
  5. 페이징, 정렬 등의 쿼리가 가능하다.

  6. platform-independent query language. (oracle, mysql, etc…)
  7. jpql queries can be dynamically and statically
  8. perform join operations.
  9. update and delete data in a bulk.
  10. perform aggregate function with sorting and grouping clauses.

Simple start JPQL

예제에 사용할 객체이다. 실제 테이블은 다대다라 조인테이블이 있고 Teacher 에 subject_id 컬럼이 있다.
jpql_table

em.createQuery로 jpql을 시작 할 수 있는데 안의 변수로는 String만 지정하면 Object[]이 리턴되고 String과 리턴할 엔티티 클래스 타입으로 조회하면 해당 타입으로 리턴된다.

😀간단한 예제

final List<Teacher> teacherList = 
    em.createQuery("select t from Teacher as t", Teacher.class).getResultList();

💻console

Teacher(id=1, name=TmathA, classes=ADVANCE)
Teacher(id=2, name=TmathB, classes=BASIC)

JPQL select

jpql의 문법은 대•소문자를 가리진 않지만 조회할 엔티티는 대•소문자 구별하여 써야한다.
jpql의 기본 조회인 select에 대해 알아보자.
from 절 뒤에 엔티티가 오는데 꼭 alias를 주어야 한다.

SELECT t FROM Teacher as t  -- Teacher 테이블 모든 컬럼 조회
SELECT t.subject FROM Teacher as t  -- 조인된 Subject 테이블 조회
SELECT DISTINCT t.id, t.name FROM Teacher as t  -- 지정 컬럼 조회

엔티티를 가져올 때는 TypedQuery로 String 뒤에 Class 타입을 줘서 편하게 가져올 수 있는데 3번째 지정 컬럼 조회는 Object[]로 가져와야한다.
😀example

final List resultList = em.createQuery("select t.id, t.name from Teacher as t").getResultList();
for (Object o : resultList) {
    Object[] field = (Object[]) o;
    Long id = (Long) field[0];
    String name = (String) field[1];
    System.out.println("id : " +id + " name : " + name);
}

💻console

id : 1 name : TmathA
id : 2 name : TmathB

Object배열로 조회하는것은 가독성이 좋지 않다. TypedQuery의 클래스로 Dto로 받을 수 있지만 Dto의 패키지를 모두 적어줘야한다.

// new 로 생성자를 만드는 문법과 같다.
final List<TeacherDto> resultList = em.createQuery("select new jpastudy.dto.TeacherDto(t.id, t.name) from Teacher as t", TeacherDto.class).getResultList();

JPQL grammer

JPQL은 SQL의 기본 문법인 where, group by, having, order by 모두 지원한다.

String orderByQuery = "select s from Student as s where s.grades > 50 order by s.grades desc";
final List<Student> studentList =
        em.createQuery(orderByQuery, Student.class).getResultList();

💻console

Student(id=10, name=student9, classes=ADVANCE, grades=99)
Student(id=86, name=student85, classes=ADVANCE, grades=99)
Student(id=1, name=student0, classes=ADVANCE, grades=98)
Student(id=16, name=student15, classes=ADVANCE, grades=98)
•••

Paging

페이징도 jpa에서 정말 간단히 추상화 해놓았다. setFirstResult로 시작값 setMaxResults로 조회할 갯수를 불러오면 된다.
setFirstResult시 시작은 0임을 주의하자.

final List<Student> studentList =
        em.createQuery("select s from Student as s order by s.id asc", Student.class)
                .setFirstResult(3) // 시작은 0부터라 4번째 것부터 불러온다.
                .setMaxResults(5)
                .getResultList()
        ;

💻console

Student(id=4, name=student3, classes=BASIC, grades=21)
Student(id=5, name=student4, classes=BASIC, grades=20)
Student(id=6, name=student5, classes=ADVANCE, grades=60)
Student(id=7, name=student6, classes=ADVANCE, grades=56)
Student(id=8, name=student7, classes=BASIC, grades=24)

Error Log

💻console

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "
•••
Caused by: java.sql.SQLSyntaxErrorException: (conn=34) Table 'jpastudy.teacher' doesn't exist

에러가 “이 들어갔다고 했는데 아래 보니 문법 에러였다.

@Entity
public class Teacher {
    @Id
    @GeneratedValue
    @Column(name = "teacher_id")
    private Long id;

    private String name;

    @Enumerated(value = EnumType.STRING)
    private Group group;
    •••

여기서 group가 예약어이기 때문에 teacher이 만들어지지않아 에러가 발생했다.

Reference

https://www.javatpoint.com/jpa-jpql-introduction
https://www.objectdb.com/java/jpa/query/jpql/structure

태그: ,

카테고리:

업데이트:

댓글남기기