JPA Java Persistence Query Language
What is JPQL
JPQL은 Java Persistence Query Language 의 약자로 Java의 객체지향 쿼리 언어이다.
JPQL은 데이터베이스 테이블 대신 엔티티 개체 모델을 사용하여 SQL 쿼리를 실행한다.
(👍Tip : JPA는 JPQL을 방언에 따라 적합한 데이터베이스의 SQL로 변환하는 것이다.)
Benefits of JPQL
- DB에 독립적이다. SQL을 추상화하여 특정 DB에 종속되지 않음.
(oracle, mysql등 데이터베이스 방언으로 교체가능) - 동적 또는 정적 쿼리가 가능하다.
- 조인 동작이 수행된다. (기본조인 뿐만 아니라 페치조인)
- update, delete로 한 번에 많은 데이터 처리가 가능하다.
-
페이징, 정렬 등의 쿼리가 가능하다.
- platform-independent query language. (oracle, mysql, etc…)
- jpql queries can be dynamically and statically
- perform join operations.
- update and delete data in a bulk.
- perform aggregate function with sorting and grouping clauses.
Simple start JPQL
예제에 사용할 객체이다. 실제 테이블은 다대다라 조인테이블이 있고 Teacher 에 subject_id 컬럼이 있다.
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
댓글남기기