@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<>();
}
@Entity
@Table(name = "ORDERS")
public class Order {
@Id
@GeneratedValue
private Long id;
private int orderAmount;
@Embedded
private Address address;
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product;
}
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
private int price;
private int stockAmount;
}
@Embeddable
public class Address {
private String city;
private String street;
private String zipcode;
}
문법
select m from Member as m where m.age > 18
Entity와 속성은 대소문자를 구분한다.
Entity
Member
속성
age
JPQL 키워드는 대소문자를 구분하지 않는다.
ex. select, from, where
테이블 이름이 아니라 Entity 이름을 사용해야 한다.
ex. Member
@Entity(name = "") 값으로 설정된다.
기본 값은 클래스와 같은 이름이다.
별칭은 필수로 사용해야 한다.
ex. as m
as는 생략 가능하다.
집합과 정렬
group by, having등도 똑같이 사용하면 된다.
TypeQuery, Query 타입
TypeQuery
public class JpaMain {
public static void main(String[] args) {
TypedQuery<Member> a = em.createQuery("select m from Member m", Member.class);
TypedQuery<String> b = em.createQuery("select m.username from Member m", String.class);
}
}
반환 타입이 명확할 때 사용한다.
Query
public class JpaMain {
public static void main(String[] args) {
// username과 age는 타입이 달라서 명시할 수 없으므로 Query 타입을 사용한다.
Query a = em.createQuery("select m.username, m.age from Member m");
}
}
반환 타입이 명확하지 않을 때 사용한다.
결과 조회 API
query.getResultList()
결과가 하나 이상일 때 리스트를 반환한다.
결과가 없으면 빈 리스트를 반환한다.
query.getSingleResult()
결과가 정확히 하나일 때 단일 객체를 반환한다.
javax.persistence.NoResultException
결과가 없을 때
결과가 당연히 없을 수도 있는 건데 try-catch로 다시 처리해줘야 해서 불편하다.
Spring Data JPA를 사용하면 Optional로 반환해 예외를 던지지 않는다.
javax.persistence.NonUniqueResultException
결과가 2개 이상일 때
파라미터 바인딩
이름 기준
public class JpaMain {
public static void main(String[] args) {
Member singleResult = em
.createQuery("SELECT m FROM Member m where m.username=:username", Member.class)
.setParameter("username", "member1");
System.out.println(singleResult.getUserName());
}
}
이름으로 지정해서 가져오기 때문에 순서가 뒤바뀌는 실수가 발생하지 않는다.
위치 기준
public class JpaMain {
public static void main(String[] args) {
TypedQuery<Member> query = em
.createQuery("SELECT m FROM Member m where m.username=?1", Member.class);
query.setParameter(1, usernameParam);
}
}