Java Persistence Query Language
JPQL은 객체지향 쿼리 언어
테이블 대상이 아니라 자바 내의 엔티티 객체 대상.
JPQL은 SQL을 추상화 한 것이라 특정DB에 의존하지 않음.
JPQL은 결국 SQL로 변환됨.
예제
JPQL 해볼 예제임.
코드
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String username;
private int age;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
팀과 상호 연관관계. Many쪽인 Member가 주인.
@Entity
@Table(name = "orders")
public class Order {
@Id @GeneratedValue
private Long id;
private int orderAmount;
@Embedded
Address address;
@ManyToOne
@JoinColumn(name = "product_id")
private Product product;
}
Embedded 타입 사용.
@Embeddable
public class Address {
private String city;
private String street;
private String zipcode;
}
Hibernate:
create table orders (
orderAmount integer not null,
id bigint not null,
product_id bigint,
city varchar(255),
street varchar(255),
zipcode varchar(255),
primary key (id)
)
제대로 잘 들어 감.
@Entity
public class Product {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
private int stockAmount;
}
order와 product는 단방향 연관관계.
order가 다 쪽.
여튼 환경은 이렇고, 본격적으로 JPQL 문법.
sql이랑 거의 똑같다.
join 등 약간 다른 부분이 있긴 하다.
벌크 연산 이란 것이 있다.
한번에 회사원들 연봉 10% 인상한다던지 한번에 여러 개 연산.
나중에 배움
문법
select m from Member as m where m.age > 18
거의 비슷한데, 약간 다른 건 저 Member가 테이블이 아닌 객체
엔티티와 속성은 대소문자 구분한다. 객체랑 필드 대소문자 구분 하듯이.
select from where같은 키워드는 대소문자 구분X
별칭은 필수이다. as 생략가능.
sql 함수
다 제공 됨.
group by, having
order by 똑같이 쓰면 됨.
반환타입 명확할 때 : TypedQuery
명확하지 않을 때 : Query
TypedQuery<Member> tyQuery = em.createQuery("select m from Member m", Member.class);
Query query = em.createQuery("select m.username, m.age from Member m");
이런 거.
위는 반환타입이 명확하니 TypedQuery
아래에는 명확하지 않음.
예를 들어 m.username만 가지고 오면 String으로 명확하게 할 수 있었는데.
결과조회
결과가 하나 이상일때
TypedQuery<Member> tyQuery = em.createQuery("select m from Member m", Member.class);
List<Member> members = tyQuery.getResultList();
query.getResultList()
TypedQuery<Member> tyQuery = em.createQuery("select m from Member m where m.id = "+ id, Member.class);
Member member = tyQuery.getSingleResult();
하나만 가져올 때.
query.getSingleResult();
근데 좀 주의할 게 있음
getResultList() : 결과가 하나이상일 때 쓰는 것이고, 결과 없으면 빈 리스트 반환
getSingleResult() : 결과가 정확히 하나여야 함.
없으면 javax.persistence.NoResultException
결과가 둘 이상이면 javax.persistence.NonUniqueResultException 던짐
파라미터 바인딩
TypedQuery<Member> tyQuery = em.createQuery("select m from Member m where m.id = :id", Member.class);
tyQuery.setParameter("id", 3);
Member member = tyQuery.getSingleResult();
이런 식으로.
:id 해서 이름바인딩
query.setParameter("이름", 값);
참고로,
Member memeber = em.createQuery("select m from Member m where m.id = :id", Member.class)
.setParameter("id",3)
.getSingleResult();
이렇게 쓰라고 만든거임. 저렇게 안나눠도 됨.
그리고, 바인딩 할 때 이름기준 말고 위치기준도 있긴 한데, (:이름 대신 ?1 하면서 순서 넣는거)
그냥 이름 쓰셈. 그게 더 명확함.
'JPA > JPA 기본' 카테고리의 다른 글
40. 페이징 (0) | 2023.10.31 |
---|---|
39. 프로젝션(select) (0) | 2023.10.30 |
37. JPQL (0) | 2023.10.30 |
36. 값타입 실전 (0) | 2023.10.30 |
35. 값타입 컬렉션 (0) | 2023.10.29 |