68
데이터 접근프레임워크 (JPA와 Hibernate) 교육기간 : 2014.05.26 ~ 05.30 강사 : 박석재, 임병인 넥스트리소프트㈜ [email protected] [email protected]

데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

  • Upload
    others

  • View
    10

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

데이터 접근프레임워크

(JPA와 Hibernate)

교육기간 : 2014.05.26 ~ 05.30

강사 : 박석재, 임병인 넥스트리소프트㈜ [email protected]

[email protected]

Page 2: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 1 - 과정명 : JPA와 Hibernate

교육 일정표

교육은 매 회 3 시간씩 총 5회에 걸쳐 진행합니다.

1 일차 2 일차 3 일차 4 일차 5 일차

5월 26일(월) 5월 27일(화) 5월 28일(수) 5월 29일(목) 5월 30일(금)

ORM 이해하기

• 영속성

• 패러다임 불일치

• 계층형 아키텍처

• 객체/관계형 매핑

• Quick Start

- Hibernate

• Hibernate 개요

• Hibernate 기본

• OR Mapping I

- Hibernate

• Spring과 Hibernate통합

• OR Mapping II

• 트랜잭션 관리

• Hibernate와 EJB

- JPA

• 도메인 모델과 JPA

• JPA 이용 도메인 객체 구현

• 엔티티 관계

• 엔티티 매핑

• 엔티티 관계 매핑

- JPA

• 상속 매핑

• EntityManager

• 질의 API

• JPQL

Page 3: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

5.1 상속 매핑

5.2 EntityManager

5.3 질의API와 JPQL

5일차 – JPA

단일 테이블 전략

조인 테이블 전략

클래스 별 테이블 전략

다형성 관계 매핑

Page 4: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 3 - 과정명 : JPA와 Hibernate

단일 테이블 전략

상속계층의 모든 클래스를 한 테이블로 매핑함

식별자(discriminator) 컬럼으로 계층 상의 객체를 구분함

식별자 컬럼은 객체의 타입 값을 가짐

매핑 annotation

식별자 컬럼

@Entity

@Table(name="USERS")

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(name="USER_TYPE",

discriminatorType=DiscriminatorType.STRING, length=1)

public abstract class User ...

@Entity

@DiscriminatorValue(value="S")

public class Seller extends User ...

@Entity

@DiscriminatorValue(value="B")

public class Bidder extends User

Page 5: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 4 - 과정명 : JPA와 Hibernate

조인 테이블 전략

일대일 관계를 이용하여 상속을 표현

각 엔티티 별로 테이블을 나누며, 상속 관계는 일대일 관계로 표현

부모 클래스에 해당하는 테이블은 자식 클래스들의 공통인 컬럼을 가짐

매핑 annotation @Entity

@Table(name="USERS")

@Inheritance(strategy=InheritanceType.JOINED)

@DiscriminatorColumn(name="USER_TYPE",

discriminatorType=STRING, length=1)

public abstract class User ...

@Entity @Table(name="SELLERS") @DiscriminatorValue(value="S") @PrimaryKeyJoinColumn(name="USER_ID") public class Seller extends User ... @Entity @Table(name="BIDDERS") @DiscriminatorValue(value="B") @PrimaryKeyJoinColumn(name="USER_ID") public class Seller extends User ...

Page 6: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 5 - 과정명 : JPA와 Hibernate

클래스 별 테이블 전략

상속 계층 상의 모든 클래스가 각각 테이블로 매핑되며 테이블은 관계가 없음

OO / Relational 관점에서 모두 바람직하지 않음

엔티티 검색시 SQL UNION을 사용하거나 각 엔티티를 별도의 SQL로 검색해야 함

@Entity

@Table(name="USERS")

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

public class User {

...

@Entity

@Table(name="SELLERS")

public class Seller extends User {

...

@Entity

@Table(name="BIDDERS")

public class Bidder extends User {

Page 7: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 6 - 과정명 : JPA와 Hibernate

상속 매핑 전략 비교

상속 매핑 전략 선택은 많은 고민을 필요로 함

특성 단일 테이블 조인 테이블 클래스 별 테이블

테이블 지원 모든 클래스를 한 테이블에 •컬럼이 널 가능 •하위 클래스 추가시 테이블이 확장됨

부모 클래스, 자식 클래스가 별도의 테이블로 매핑되고 조인으로 서로 묶음 매핑된 테이블은 정규화 됨

각 클래스 별 한 테이블이며 조인 관계 없음

식별자 컬럼 사용 예 예 아니오

엔티티 계층 검색 SQL 생성 단순 SELECT 조인을 포함한 SELECT 각 클래스별 하나의 SELECT 또는 SELECT의 UNION 사용

삽입/갱신을 위한 SQL 하나의 INSERT/UPDATE 여러 INSERT/SELECT, 부모 클래스와 각 하위 클래스용

각 클래스별 하나의 INSERT/UPDATE

다형성 관계 좋음 좋음 나쁨

다형성 질의 좋음 좋음 나쁨

EJB3 JPA 지원 필수 필수 선택사항

Page 8: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

5.1 상속 매핑

5.2 EntityManager

5.3 질의API와 JPQL

5일차 – JPA

EntityManager소개

EntityManager 인스턴스 생성

지속성 오퍼레이션 관리

엔티티라이프사이클 리스너

엔티티 운영 가이드

Page 9: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 8 - 과정명 : JPA와 Hibernate

EntityManager소개 : EntityManager 인터페이스 (1/2)

EntityManager

객체지향과 관계형 간의 다리 역할

도메인 객체를 테이블로 변환

엔티티 저장요청 시: 엔티티 객체를 생성하여, 데이터베이스 저장한 다음 객체지향 세계로 리턴하여 줌

SQL과 같은 CRUD 오퍼레이션 제공

강력한 기능에 비해 상대적으로 작고 단순하며 직관적인 인터페이스를 가짐

Page 10: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 9 - 과정명 : JPA와 Hibernate

EntityManager소개 : EntityManager 인터페이스 (2/2)

메소드 시그너처 설명

public void persist(Object entity); 엔티티를 DB로 저장

public <T> T merge(T entity); EntityManager의 지속성 컨텍스트로 엔티티를 병합

public void remove(Object entity); DB로 부터 엔티티 삭제

public <T> T find(Class<T> entityClass, Object primaryKey); 일차키로 엔티티 인스턴스를 찾음

public void flush(); EntityManager의 지속성 컨텍스트 안의 엔티티를 DB와 동기화 함

public void setFlushMode(FlushModeType flushMode); EntityManager의 지속성 컨텍스트의 flush 모드를 변경함 (AUTO 또는 COMMIT)

public FlushModeType getFlushMode(); 현재 플러시 모드 검색

public void refresh(Object entity); DB의 엔티티를 리셋함

public Query createQuery(String jpqlString); JPQL 문을 이요하여 동적 질의 생성

public Query createNamedQuery(String name); 질의 인스턴스 생성

public Query createNativeQuery(String sqlString); public Query createNativeQuery(String sqlString, Class result Class); public Query createNativeQuery(String sqlString, String resultSetMapping);

원시 SQL문을 이용하여 동적 질의 생성

public void close(); EntityManager를 종료함

public boolean isOpen(); EntityManager 실행상태 확인

public EntityTransaction getTransaction(); 트랜잭션 객체 검색

public void joinTransaction(); 기존 JTA 트랜잭션 조인을 요청함

Page 11: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 10 - 과정명 : JPA와 Hibernate

EntityManager소개 : 엔티티 라이프사이클

엔티티는 아주 단순한 라이프사이클을 가짐

SessionBean이나 MDB는 애플리케이션 시작과 함께 컨테이너로 로드됨

반면, EntityManager는 JPA 엔티티로 인식하기 전에는 POJO를 알지 못함

SessionBean이나 MDB는 처음부터 끝까지 컨테이너가 인식함

반면, EntityManager는 가능한 짧은 시간동안 엔티티를 인식하고 다루어야 함

관리되는 엔티티(managed entity)

Page 12: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 11 - 과정명 : JPA와 Hibernate

EntityManager소개 : 지속성 컨텍스트, 범위, EntityManager (1/2)

지속성 컨텍스트(persistence context)

주어진 지속성 범위 내에서 EntityManager에 의해 관리되는 엔티티 컨테이너의 집합

지속성 범위는 엔티티를 관리하고 있는 기간임, 다음 두 가지 유형이 있음

• 트랜잭션(transaction)

• 확장 (extended)

EntityManager의 내부 기능에 가장 중요한 역할을 수행함

EntityManager는 엔티티의 상태관리를 현재 가용한 지속성 컨텍스트로 위임함

트랜잭션-범위 EntittyManager

트랜잭션 기간 동안 엔티티는 attach 상태이고, 종료 후 자동으로 detach 상태가 됨

Page 13: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 12 - 과정명 : JPA와 Hibernate

EntityManager소개 : 지속성 컨텍스트, 범위, EntityManager (2/2)

확장-범위 EntityManager

여러 트랜잭션을 걸쳐서 라이프사이클이 지속됨

유상태 세션 빈과 함께 사용하고 빈 인스턴스가 살아있는 동안 계속 됨

엔티티의 관리대상 여부는 트랜잭션과 관계없음

빈 자체가 제거되든지 EntityManager가 종료되어야 범위가 끝남

Page 14: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 13 - 과정명 : JPA와 Hibernate

EntityManager소개 : ActionBazaar 에서 EntityManager 사용

@Stateless

public class ItemManagerBean implements ItemManager {

@PersistenceContext(unitName="actionBazaar")

private EntityManager entityManager;

public ItemManagerBean() {}

public Item addItem(String title, String description, byte[] picture, double initialPrice, long sellerId) {

Item item = new Item();

item.setTitle(title);

item.setDescription(description);

item.setPicture(picture);

item.setInitialPrice(initialPrice);

Seller seller = entityManager.find(Seller.class, sellerId);

item.setSeller(seller);

entityManager.persist(item);

return item;

}

public Item updateItem(Item item) {

entityManager.merge(item);

return item;

}

public Item undoItemChanges(Item item) {

entityManager.refresh(entityManager.merge(item));

return item;

}

public void deleteItem(Item item) {

entityManager.remove(entityManager.merge(item));

}

}

Page 15: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 14 - 과정명 : JPA와 Hibernate

EntityManger 인스턴스생성 : 컨테이너-관리 EntityManager

Container-managed EntityManager

@PersistenceContext annotation을 이용 주입됨

지속성 유닛은 소스코드로 설정할 수 없으므로 persistence.xml에 설정함

admin 유닛을 위한 EntityManager 얻기

@PersistenceContext(unitName="admin")

EntityManager entityManager;

일반적으로 Java EE 모듈은 하나의 지속성 유닛을 가짐

EntityManager 범위설정

범위는 엔티티의 타입에 따라 결정됨(transaction or extended)

@PersistenceContext(type=PersistenceContextType.EXTENDED)

EntityManager entityManager;

무상태 세션빈이나 MDB는 확장-지속성 범위를 가질 수 없음

유상태 세션빈은 확장-지속성 범위를 가질 수 있음

Page 16: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 15 - 과정명 : JPA와 Hibernate

EntityManger 인스턴스생성 : 애플리케이션-관리 EntityManager

애플리케이션-관리 EntityManager

Java-EE 컨테이너로부터 아무것도 원하지 않음

즉, EntityManager의 라이프사이클을 위한 모든 코드를 직접 작성해야 함

Java SE 나 Tomcat과 같은 경량급 웹 컨테이너만 있는 곳에서 사용

Java EE 컨테이너 내에서도 EntityManager에 대한 세심한 통제가 필요한 곳에 사용가능

@Stateless

public class ItemManagerBean implements ItemManager {

@PersistenceUnit

private EntityManagerFactory entityManagerFactory;

private EntityManager entityManager;

public ItemManagerBean() {}

@PostConstruct

public void initialize() {

entityManager = entityManagerFactory.createEntityManager();

}

public Item updateItem(Item item) {

entityManager.joinTransaction();

entityManager.merge(item);

return item;

}

@PreDestroy

public void cleanup() {

if (entityManager.isOpen()) {

entityManager.close();

}

}

...

}

Page 17: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 16 - 과정명 : JPA와 Hibernate

지속성 오퍼레이션 관리 : 엔티티 저장

EntityManager.persist() 인터페이스

Item은 Seller와 다대일 관계를 가지고 있음

persist()는 새로 생성하는 것이지 갱신(update)하는 것이 아님

따라서, persist() 대상 객체의 일차키나 identity가 DB에 존재하지 않아야 함

public Item addItem(String title, String description, byte[] picture, double initialPrice, long sellerId) {

Item item = new Item();

item.setTitle(title);

item.setDescription(description);

item.setPicture(picture);

item.setInitialPrice(initialPrice);

Seller seller = entityManager.find(Seller.class, sellerId);

item.setSeller(seller);

entityManager.persist(item);

return item;

}

Page 18: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 17 - 과정명 : JPA와 Hibernate

지속성 오퍼레이션 관리 : 일차키로 엔티티 검색

EntityManager.find() 인터페이스

일차키로 엔티티 인스턴스 검색

Seller seller = entityManager.find(Seller.class, sellerId);

• 첫번째 파라미터: 엔티티의 자바 타입

• 두번째 파라미터: 엔티티 인스턴스의 identity 값

• identity는 @Id, @IdClass, @EmbeddableId를 이용하여 지정

복합키 사용

SellerPK sellerKey = new SellerPK();

sellerKey.setFirstName(firstName);

sellerKey.setLastName(lastName);

Seller seller = entityManager.find(Seller.class, sellerKey);

검색 결과가 없을 경우 null이나 빈 객체를 리턴함

내부 캐시를 활용함으로써 성능을 높임

데이터 로드 시 두 가지 모드(lazy / eager)를 사용함 @Column(name="PICTURE")

@Lob

@Basic(fetch=FetchType.LAZY)

public byte[] getPicture() {

Page 19: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 18 - 과정명 : JPA와 Hibernate

지속성 오퍼레이션 관리 : 엔티티 갱신 (1/2)

갱신(update)

EntityManager는 엔티티의 모든 변경을 DB에 반영함

따라서, 애플리케이션은 갱신에 대해 신경쓸 필요 없음

아래 예제에서 seller는 관리상태이므로 DB와 데이터 동기화를 뒤에서 처리하여 줌

public void calculateCreditWorthiness (Long sellerId) {

PowerSeller seller = entityManager.find (PowerSeller.class, sellerId);

seller.setCreditWorth(seller.getCreditWorth()

* CREDIT_FACTOR

* getRatingFromCreditBureauRobberBarons(seller));

seller.setCreditWorth(seller.getCreditWorth()

+ (seller.getCreditWorth()

* FEEDBACK_FACTOR

* seller.getBuyerFeedbackRating()));

seller.setCreditWorth(seller.getCreditWorth()

+ (seller.getCreditWorth()

* SELLING_FACTOR

* getTotalHistoricalSales(seller)));

}

Page 20: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 19 - 과정명 : JPA와 Hibernate

지속성 오퍼레이션 관리 : 엔티티 갱신 (2/2)

detach/attach 오퍼레이션

EntityManager가 트랜잭션 범위에서 사용될 때, 트랜잭션이 종료되면 detach됨

따라서, 세션빈이 리턴하는 모든 엔티티는 detach 상태임

예, “엔티티 저장”에서 addItem() 메소드가 리턴하는 Item은 detach 상태임

엔티티 갱신을 위해서는 reattacht(== merge) 함 public Item updateItem(Item item) {

entityManager.merge(item);

return item;

}

Page 21: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 20 - 과정명 : JPA와 Hibernate

지속성 오퍼레이션 관리 : 엔티티 삭제

엔티티 삭제

우선 EntityManager에 merge()한 후 remove()함

현재 attach 상태에 있는 엔티티만 삭제할 수 있기 때문임

Bidder 엔티티가 삭제될 때 BillingInfo 객체를 함께 삭제

일대다 관계에서 다(many)측의 객체를 삭제할 때, 일(one)측의 객체를 함께 삭제할 때 주의를 요함

public void deleteItem(Item item) {

entityManager.remove(entityManager.merge(item));

}

@Entity

public class Bidder {

@OneToOne(cascade=CascadeType.REMOVE)

public BillingInfo setBillingInfo() {

Page 22: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 21 - 과정명 : JPA와 Hibernate

지속성 오퍼레이션 관리 : flush()로 갱신 제어

EntityManager.flush()

flush() 를 모를 경우 불리할 수 있음

persist(), merge(), remove() 오퍼레이션 결과가 바로 DB에 반영되지 않음

flush()가 호출될 때까지 반영은 늦추어짐

이러한 메커니즘은 불필요한 DB 접근을 막아서 수행성능을 높이기 위한 것임

flush 모드 – AUTO/COMMIT

디폴트 DB flush 모드는 AUTO 임, EntityManager가 필요할 때 자동으로 flush()호출

트랜잭션 범위 EntityManager의 경우, 트랜잭션 종료 시점에 flush() 호출

확장 범위 EntityManager의 경우, 지속성 컨텍스트가 닫히는 시점에 flush() 호출

반영되지 않은 변경은 다음 질의어 수행 전에 flush() 호출

COMMIT 모드 – 커밋 시에만 flush() 호출

entityManager.setFlushMode(FlushModeType.COMMIT);

모드 변경은 매우 비용이 많이 드는 오퍼레이션 임

entityManager.flush();

Page 23: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 22 - 과정명 : JPA와 Hibernate

지속성 오퍼레이션 관리 : 엔티티 리프레시

EntityManager.refresh()

DB로부터 관리 중인 모든 엔티티를 다시 읽어옴(repopulate)

undo 오퍼레이션 후에 refresh() 호출은 매우 유익함

refresh() 전에 항상 merge() 함

persist() 오퍼레이션 호출 후 바로 DB에 반영되지 않는 상황에서 사용할 수 있음

public Item undoItemChanges(Item item) {

entityManager.refresh(entityManager.merge(item));

return item;

}

public Item addItem(String title, String description, byte[] picture, double initialPrice, long sellerId) {

Item item = new Item();

item.setTitle(title);

...

entityManager.persist(item);

entityManager.flush();

entityManager.refresh(item);

return item;

}

Page 24: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 23 - 과정명 : JPA와 Hibernate

엔티티 라이프사이클 리스너 : 엔티티 리스너 사용

엔티티 상태 모니터링

Callback 엔티티는 무상태임

예, Item의 입찰금액이 지정한 값을 넘었을 때, 통지하는 경우

리스너 클래스는 DI를 지원하지 않음, 엔티티가 DI 컨테이너 밖에서 존재할 수 있음

public class ItemMonitor {

...

public ItemMonitor() {}

@PrePersist

@PreUpdate

public void monitorItem(Item item) {

if (item.getInitialBidAmount() > ItemMonitor.MONITORING_THRESHOLD) {

notificationManager.sendItemPriceEmailAlert(item);

}

}

}

@Entity

@EntityListeners(actionbazaar.persistence.ItemMonitor.class)

public class Item implements Serializable {

Callback 지정

리스너 등록

Page 25: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 24 - 과정명 : JPA와 Hibernate

엔티티 라이프사이클 리스너 : 기본 리스너 클래스

감사 또는 트랜잭션 로그

모든 엔티티에 대한 변화를 기록함

이 경우 기본 리스너를 활용할 수 있음, 모든 엔티티의 모든 지속성 오퍼레이션을 로깅

annotation을 이용하여 지정할 법이 없음

persistence.xml을 이용하여 기본 리스너 지정

public class ActionBazaarAuditor {

...

@PrePersist

@PostPersist

...

@PostRemove

public void logOperation(Object object) {

Logger.log("Performing Persistence Operation on: “ + object.getName());

<persistence-unit name="actionBazaar">

...

<default-entity-listeners>

actionbazaar.persistence.ActionBazaarAuditor.class

</default-entity-listeners>

...

Page 26: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 25 - 과정명 : JPA와 Hibernate

엔티티 라이프사이클 리스너 : 리스너 클래스 실행순서

실행 순서

기본 리스너, 엔티티 클래스 특정 리스너, 부모 클래스 리스너 등이 존재함

기본 리스너가 가장 먼저 실행됨, 다음으로 부모 클래스 리스너, ...

동일한 유형의 리스너가 여러 개 일 경우 나열된 순서대로 실행

실행 순서는 프로그램으로 제어할 수 없지만, 기본 리스너와 부모 리스너를 제외가능

EntityListeners({actionbazaar.persistence.

ItemMonitor.class, actionbazaar.persistence.

ItemMonitor2.class})

@Entity

@ExcludeDefaultListeners

@ExcludeSuperClassListeners

@EntityListeners(actionbazaar.persistence.SellerMonitor.class)

public class Seller extends User {

Page 27: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 26 - 과정명 : JPA와 Hibernate

엔티티 운영 가이드

컨테이너-관리 엔티티 관리자를 사용할 것

EntityManager를 웹-티어로 주입(injecting)하지 말 것

엔티티 접근 객체 패턴을 사용할 것

콜백을 외부 리스너와 분리할 것

Page 28: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

5.1 상속 매핑

5.2 EntityManager

5.3 질의API

5.4 JPQL

5일차 – JPA

질의 API소개

질의 실행

Page 29: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 28 - 과정명 : JPA와 Hibernate

질의 API

질의 API 소개 : 개요

지금까지 EntityManager.find를 이용하여 엔터티를 검색하였으며, 이는 ID나 일차키로 엔터티를 검색하는 것임

질의 API는 최적화된 질의어를 작성할 수 있게 해줌

EntityManager의 인터페이스와 java.persistence.Query 인터페이스를 이용하여 질의어 정의, 파라미터 바인딩, 실행, 페이지 처리 등을 수행함

JPA 질의 API는 JPQL이나 SQL 모두를 사용하여 질의를 작성할 수 있음

SQL 보다는 JPQL에 집중할 예정임

SQL은 레코드를 리턴하지만, JPQL은 엔티티를 리턴함

EntityManager query methods

Query interface

JPQL

JDBC 질의 단계(SQL) JPA 질의 단계(JPQL)

1. DB 커넥션 획득 1. EntityManager 인스턴스 획득

2. 질의문 생성 2. 질의 인스턴스 생성

3. 질의문 실행 3. 질의 실행

4. 결과검색(DB 레코드) 4. 결과 엔터티 검색

Page 30: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 29 - 과정명 : JPA와 Hibernate

질의 API 소개 : 질의(query) 분석

질의(query) 타입

지명(named) 질의: 저장한 후 재사용함

동적(dynamic, or ad hoc) 질의: 실행 시점에 다양한 환경에 맞추어 생성됨

동적 질의 예

모든 카테고리를 검색하고자 함, JPQL 이용

지명 질의일 경우: em.createNamedQuery() 호출

@PersistenceContext em; EntityManager 주입

...

public List findAllCategories() {

Query query = em.createQuery("SELECT c FROM Category c"); ...

return query.getResultList();

}

Page 31: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 30 - 과정명 : JPA와 Hibernate

질의 API 소개 : 지명(named) 질의 (1/2)

개요

사용하기 전에 미리 정의해야 함

annotation을 이용하거나 Xml 메타데이터를 이용하여 정의할 수 있음

지명질의는 인스턴스를 만들 때 이름을 이용하여 접근함

지명 질의의 장점

질의의 재사용을 높임

코드의 유지보수를 용이하게 함, 질의가 비즈니스 로직에 흩어지지 않음

수행성능을 높임, 한 번 준비되면 효율적으로 재사용됨

annotation을 사용한 지명 질의의 예

@Entity

@NamedQuery(

name = "findAllCategories",

query = "SELECT c FROM Category c WHERE c.categoryName

LIKE :categoryName ")

public class Category implements Serializable {

...

}

Page 32: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 31 - 과정명 : JPA와 Hibernate

질의 API 소개 : 지명(named) 질의 (2/2)

여러 개의 지명 질의

javax.persistence.NamedQueries 주석(annotation) 사용

지속성 유닛 범위이므로 범위 내에서 질의 이름이 유일해야 함

@Entity

@NamedQueries({

@NamedQuery(

name = "findCategoryByName",

query = "SELECT c FROM Category c WHERE c.categoryName

LIKE :categoryName order by c.categoryId"

),

@NamedQuery(

name = "findCategoryByUser",

query = "SELECT c FROM Category c JOIN c.user u

WHERE u.userId = ?1"

)})

@Table(name = "CATEGORIES")

public class Category implements Serializable {

}

Page 33: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 32 - 과정명 : JPA와 Hibernate

질의 실행 : 질의 인스턴스 생성 (1/2)

EntityManager 인터페이스

질의 인스턴스를 생성하기 위한 메소드 제공

원시 SQL 질의 생성을 위한 메소드도 제공

지명 질의 인스턴스 생성

엔티티가 속한 지속성 유닛에 접근하는 모든 컴포넌트로부터 지명 질의 인스턴스 생성

오픈 상태의 EntityManager 인스턴스가 있어야 함

사용하려면 EntityManager.createNamedQuery() 메소드를 호출함

• Query queyr = em.createNamedQuery(“findAllCategories”);

메소드 시그너처 설명

public Query createQuery(String jpqlString); JPQL 문을 이요하여 동적 질의 생성

public Query createNamedQuery(String name); 질의 인스턴스 생성

public Query createNativeQuery(String sqlString); public Query createNativeQuery(String sqlString, Class result Class); public Query createNativeQuery(String sqlString, String resultSetMapping);

원시 SQL문을 이용하여 동적 질의 생성

Page 34: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 33 - 과정명 : JPA와 Hibernate

질의 실행 : 질의 인스턴스 생성 (2/2)

동적 질의 인스턴스 생성

EntityManager가 가용한 곳 어디서든지 동적 질의 생성 가능함

• 세션빈, MDB, 웹 애플리케이션, 컨테이너 외부

• EJB 2 에서는 동적 질의를 지원하지 않음

질의 생성: EntityManager.createQuery()

• 타당한 JPQL 문을 파라미터로 전달

EntityManager가 컨테이너-관리든 애플리케이션-관리든 상관없음

질의 생성 예

• Query query = em.createQuery(“SELECT i FROM Item i”);

JPQL은 SQL과 유사하지만 JPQL 사용를 권장함

Page 35: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 34 - 과정명 : JPA와 Hibernate

질의 실행 : 질의 인터페이스 사용 (1/5)

질의 인터페이스

질의 실행을 위한 메소드 정의

질의 인스턴스를 위한 파라미터 설정 메소드 정의

페이지 처리, 플러시 모드 제어 등을 위한 메소드 정의

SQL과 JPQL은 동일한 인터페이스 사용

메소드 시그너처 설명

public List getResultList() 질의 결과 세트 검색

public Object getSingleResult() 단일 결과나 객체 검색

public int executeUpdate() JPQL UPDATE나 DELETE 문 실행

public Query setMaxResults(int maxResult) 검색할 객체의 최대 갯수

public Query setFirstResult(int startPosition) 첫번째 질의 결과의 첫번째 위치

public Query setHint(String hintName, Object value) 질의를 위한 벤더 특정 힌트 설정

public Query setParameter(String name, Object value) 지명 파라미터를 위한 값 설정

public Query setParameter(String name, Date value, TemporalType temporalType)

파라미터가 Date 타입일 경우, 지면 파라미터 값 설정

... ...

Page 36: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 35 - 과정명 : JPA와 Hibernate

질의 실행 : 질의 인터페이스 사용 (2/5)

질의 인터페이스 사용 예,

미리 정의한 지명 질의로부터 질의 인스턴스 생성함

파라미터 설정

특정 가격을 가진 모든 Item 엔티티의 인스턴스 검색

• SELECT i FROM Item i WHERE i.initialPrice = ?1

파라미터는 이름이나 숫자로 지정이 가능함

• query.setParameter(1, 100.0);

여러 파라미터 설정

• SELECT i FROM Item i WHERE i.initialPrice > ?1 AND i.initialPrice < ?2

• query.setParameter(1, 100.0);

• query.setParameter(2, 200.0);

query = em.createNamedQuery("findCategoryByName");

query.setParameter("categoryName", categoryName);

query.setMaxResults(10);

query.setFirstResult(3);

List categories = query.getResultList();

Page 37: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 36 - 과정명 : JPA와 Hibernate

질의 실행 : 질의 인터페이스 사용 (3/5)

지면 파라미터 설정 - 코드 가독성을 높여 줌

• SELECT i FROM Item i WHERE i.initialPrice = :price

• query.setParameter(“price”, 100.0);

단일 엔터티 검색

하나의 엔티티만 검색

• query.setParameter(1, “Recycle from Mr. Dumpster”);

• Category cat = (Category)query.getSingleResult();

결과가 없을 경우, NoResultException

결과가 여러 개일 경우, NonUniqueResultException try {

...

query.setParameter(1, "Recycle from Mr. Dumpster");

Category cat = (Category)query.getSingleResult();

...

}catch (NonUniqueResultException ex) {

handleException(ex);

} catch (NoResultException ex) {

handleException(ex);

}

Page 38: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 37 - 과정명 : JPA와 Hibernate

질의 실행 : 질의 인터페이스 사용 (4/5)

여러 엔티티 검색

대부분의 질의는 결과 집합(set)이나 결과 리스트를 리턴함

100과 200 사이의 결과를 검색하는 질의

query.setParameter("lowPrice", lowPriceValue) 지명 파라미터 lowPrice

query.setParameter("highPrice", highPriceValue)

List items = query.getResultList();

결과 리스트가 없을 경우 빈 리스트를 리턴함, 예외를 던지지 않음

결과 리스트의 페이지 처리

수천 또는 수만 건의 검색 결과를 효율적으로 처리하는 방법이 필요함

JPA는 페이지 처리 인터페이스를 제공함

query.setMaxResults(50);

query.setFirstResult(0); 시작 오프셋 값

List items = query.getResultList();

다음 50 건을 가져오려면,

query.setMaxResults(50);

query.setFirstResult(50);

Page 39: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 38 - 과정명 : JPA와 Hibernate

질의 실행 : 질의 인터페이스 사용 (5/5)

오프셋과 페이지 사이즈를 동적으로 처리

질의 flush 모드 통제

flush 모드를 통해 EntityManager가 DB에 쓰는 방식을 결정

AUTO 모드(기본): 지속성 컨텍스트 안의 엔티티 갱신을 지속성 공급자가 책임 짐

COMMIT 모드: 지속성 컨텍스트 안의 엔티티에 대한 갱신을 정의하지 않음

대부분의 경우 AUTO 모드 사용을 권장함

public List getPagedItems(int pageIndex, int pageSize) {

...

query.setMaxResults(pageSize) ;

query.setFirstResult(pageIndex) ;

return query.getResultList();

}

Page 40: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 39 - 과정명 : JPA와 Hibernate

질의 실행 : 질의 힌트 지정

벤더 고유의 확장

질의 실행 중에 사용할 수 있는 벤더 고유의 확장 기능이 있음

확장 기능의 예, 성능 최적화, 질의 힌트 전달

질의 힌트

질의 힌트는 지속성 제공자가 질의 수행 중에 사용할 팁

예, 질의 사용 중에 캐시를 사용할 것을 지정함

TopLink 사용 시 타임아웃 시간을 10초로 설정함

• query.setHint(“toplink.jdbc.timeout”, new Integer(10000));

Hibernate 사용 시 동일한 동작

• query.setHime(“org.hibernate.timeout”, new Integer(10));

공급자의 파라미터 지정방식에 따름, 다음은 자주 쓰이는 예

• 로우 패치 크기, 캐시 모드, 캐시 리프레시, 타임아웃 @NamedQuery(

name = "findUserWithNoItems",

query = "SELECT DISTINCT u FROM User u WHERE u.items is EMPTY",

hints = { @QueryHint(name = "org.hibernate.timeout", value = "10") }

)

Page 41: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

5.1 상속 매핑

5.2 EntityManager

5.3 질의API

5.4 JPQL

5일차 – JPA

개요

문(statement) 유형 정의

FROM절 사용

조건식과 연산자

JPQL 함수 사용

SELECT절 사용

조합(aggregation)사용

질의 결과 정렬

하위-질의 사용

엔티티조인

대량 갱신과 삭제

Page 42: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 41 - 과정명 : JPA와 Hibernate

개요

JPQL(Java Persistence Query Language)

Hibernate는 HSQL 제공

Kodo는 JDO QL 제공

JPQL은 EJB 2의 EJB QL의 확장판임

JPQL은 자바 영역 안에서 클래스와 객체를 다룸

SQL은 DB 영역에서 테이블, 컬럼, 로우를 다룸

둘은 외관상 비슷하지만 완전히 서로 다른 두 영역에서 실행 됨

JPQL이 변환을 통해 SQL로 변경되는 절차

Page 43: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 42 - 과정명 : JPA와 Hibernate

문(statement) 유형 정의 (1/3)

JPQL은 세 가지 문(statement)을 제공함

SELECT: 엔티티와 엔티티 관련 데이터를 검색함

UPDATE: 하나 또는 그 이상의 엔티티를 갱신함

DELETE: 하나 또는 그 이사의 엔티티를 삭제함

SELECT 정의 및 사용

JPQL의 예,

SELECT 절: 검색할 객체 타입, 엔티티, 값 등을 지정함

FROM 절: 다른 절에서 사용할 엔티티 선언

[옵션] WHERE 절: 질의 결과를 필터링 함

[옵션] ORDER BY 절: 질의 결과 순서를 정함

[옵션] GROUP BY 절: 조합(aggregation) 수행

[옵션] HAVING 절: 조합과 결합(conjunction) 안에서 필터링 수행

SELECT c

FROM Category c

WHERE c.categoryName LIKE :categoryName

ORDER BY c.categoryId

Page 44: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 43 - 과정명 : JPA와 Hibernate

문(statement) 유형 정의 (2/3)

UPDATE와 DELETE 정의

WHERE 절에 조건을 지정함으로써 대규모 갱신 및 삭제가 가능함

SQL 문과 매우 유사함

UPDATE 사용

한 가지 엔티티 유형만 지정할 수 있음

엔티티 개수를 제한하기 위해 WHERE 절을 사용함

UPDATE 문의 구문,

성이 Packrat인 판매자의 상태를 G(Gold)로 하고 커미션비율을 10 퍼센트로 함

UPDATE entityName indentifierVariable

SET single_value_path_expression1 = value1, ...

single_value_path_expressionN = valueN

WHERE where_clause

UPDATE Seller s

SET s.status = 'G', s.commissionRate = 10

WHERE s.lastName like 'PackRat%'

Page 45: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 44 - 과정명 : JPA와 Hibernate

문(statement) 유형 정의 (3/3)

DELETE 사용

SQL 문과 매우 비슷함

하나의 엔티티 유형만 지정할 수 있음

WHERE 절에서 문의 영향을 받는 대상을 제한함

DELETE문의 구문

Silver 상태의 판매자를 모두 삭제함

DELETE entityName indentifierVariable

WHERE where_clause

DELETE Seller s

WHERE s.status= ‘Silver’

Page 46: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 45 - 과정명 : JPA와 Hibernate

FROM 절 사용 (1/4)

FROM 절

가장 중요한 절로 질의를 위한 도메인(질의 대상 엔티티)을 결정함

• FROM Category c

• Category는 도메인이며, c는 Category 타입에 대한 식별자(identifier)로 지정함

질의 도메인 지정: 엔티티 지명

@Entity 주석에서 name 요소를 사용하여 엔티티의 이름을 정의할 수 있음

name을 지정하지 않을 경우, 엔티티 클래스의 이름이 엔티티 이름이 됨

지속성 유닛 안에서 이름은 유일해야 함

Category 클래스에서 엔티티 이름 정의 예,

이 경우, FROM 절은 “FROM CategoryEntity c”

@Entity(name = "CategoryEntity")

public class Category

Page 47: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 46 - 과정명 : JPA와 Hibernate

FROM 절 사용 (2/4)

식별자(identifier) 변수

(SELECT c )FROM Category c 에서 정의된 식별자 c는 다른 절에서도 사용함

구문

FROM entityName [AS] identificationVariable

identificationVariable는 자바에서 타당한 변수여야 하며, JPQL의 예약어가 아니어야 함

다음은 JPQL의 예약어들임 유형 예약어

문(statement)과 절(clause) SELECT, UPDATE, DELETE, FROM, WHERE, GROUP, HAVING, ORDER, BY, ASC, DESC

조인 JOIN, OUTER, INNER, LEFT, FETCH

조건과 연산 DISTINCT, OBJECT, NULL, TRUE, FALSE, NOT, AND, OR, BETWEEN, LIKE, IN, AS, UNKNOWN, EMPTY, MEMBER, OF, IS, NEW, EXISTS, ALL, ANY, SOME

함수(function) AVG, MAX, MIN, SUM, COUNT, MOD, UPPER, LOWER, TRIM, POSITION, CHARACTER_LENGTH, CHAR_LENGTH, BIT_LENGTH, CURRENT_TIME, CURRENT_DATE, CURRENT_TIMESTAMP

Page 48: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 47 - 과정명 : JPA와 Hibernate

FROM 절 사용 (3/4)

경로 표현식(path expression) 이란 ?

표현식 c.categoryName, c.categoryId 등을 경로 표현식이라고 함

(.)은 항해 연산자

WHERE 절이나 ORDER BY 절에서 사용함

연관관계 필드는 단일 값 객체거나 집합 객체일 수 있음

컬렉션 값 표현식의 예,

컬렉션 값 표현식을 이용한 지속성 필드 항해 예,

• c.items.user.firstName

• c.items.user.contactDetails.email

• c.items.itemName (== category.getItems().getItemName() 와 동일함)

SELECT distinct c

FROM Category c

WHERE c.items is NOT EMPTY

Page 49: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 48 - 과정명 : JPA와 Hibernate

FROM 절 사용 (4/4)

WHERE 를 이용한 필터링

WHERE 절은 질의 결과를 필터링 함

WHERE 절이 없을 경우, 모두를 대상으로 함

조건을 지정함

WHERE 절에는 자바 상수의 거의 모든 타입 사용, boolean, float, enum, String, int 등

octal, hexadecimal, byte[], char[] 등은 사용하지 못함

SELECT c

FROM Category c

SELECT c

FROM Category c

WHERE c.categoryId > 500

Page 50: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 49 - 과정명 : JPA와 Hibernate

조건식과 연산자 (1/5)

개요

WHERE 절의 조건은 조건 표현식 또는 조건식(conditional expression)이라고 함

JPQL은 숫자, 문자열, 부울리언 값, 경로 표현식을 관계형 연산자를 이용하여 평가함

조건식의 예,

c.categoryName = ‘Dumped Cars’

연산자의 유형들

조건식의 예,

연사자 유형 연산자

항해(navigational) .

단항 부호 (unary sign) +, -

수식(arithmetic) *, /, +, -

관계(relational) =, >, >=, <, <=, <>, [NOT] BETWEEN, [NOT] LIKE, [NOT] IN, IS [NOT] NULL, IS [NOT] EMPTY, [NOT] MEMBER [OF]

논리(logical) NOT, AND, OR

WHERE c.categoryName = 'Dumped Cars'

OR c.categoryName = 'Furniture from Garbage'

Page 51: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 50 - 과정명 : JPA와 Hibernate

조건식과 연산자 (2/5)

BETWEEN을 이용한 범위 비교

수식에서 값의 범위를 비교하기 위해 BETWEEN을 사용함

BETWEEN 연산자 구문

path_expression [NOT] BETWEEN lowerRange and upperRange

범위 표현의 예,

WHERE c.categoryId BETWEEN :lowRange AND :highRange

IN 연산자 사용

경로 표현식이 리스트 값 안에 있는 지 여부를 판단하는 조건식에 IN을 사용함

IN 연산자 구문,

path_expression [NOT] IN (List_of_values)

IN 연산자를 사용한 예<

• WHERE u.userId IN (‘viper’, ‘drdba’, ‘dumster’)

• WHERE u.userId NOT IN (‘viper’, ‘drdba’, ‘dumster’)

하위 질의와 IN의 사용, (하위 질의 결과가 복수일 수 있음)

WHERE c.user IN (SELECT u FROM User u WHERE u.userType = 'A')

Page 52: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 51 - 과정명 : JPA와 Hibernate

조건식과 연산자 (3/5)

LIKE 연산자 사용

단일값 경로 표현식이 문자열 패턴과 일치하는 지 확인할 때 LIKE 연산자를 사용함

LIKE 연산자 구문

string_value_path_expression [NOT] LIKE pattern_value

• pattern_value는 상수이거나 파라미터임

• pattern_value는 (_)나 (%)를 포함할 수 있음, (_)는 단일 문자, (%)는 여러 문자를 의미함

LIKE 연산자를 사용한 예,

WHERE c.itemName LIKE ‘_ike’ mike, bike 모두 해당

(%)를 사용한 예,

WHERE c.categoryName LIKE ‘Recycle%’ Recycle로 시작하는 모든 단어

(%)를 앞뒤로 사용한 예,

WHERE c.categoryName NOT LIKE ‘%Recycle%’ Recycle이 포함되지 않음 모든 이름

파라미터를 적용한 예,

WHERE c.categoryName NOT LIKE ?1

Page 53: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 52 - 과정명 : JPA와 Hibernate

조건식과 연산자 (4/5)

널 값과 빈 컬렉션 다루기

널과 빈 문자열은 서로 다르고, JPQL은 서로 다른 방식으로 이들을 다룸

널과 빈 문자열을 동일한 방식으로 다루는 DB도 있음

빈 문자열과 널을 비교해서 true를 리턴하는 지 확인해야 함

널을 포함한 부울리언 연산 결과

NOT NULL 체크 예,

WHERE c.parentCategory IS NOT NULL

표현식 1 값 부울리언 연산자 표현식 2 값 결과

TRUE AND null UNKNOWN

FALSE AND null FALSE

Null AND null UNKNOWN

TRUE OR null TRUE

Null OR null UNKNOWN

FALSE OR null UNKNOWN

NOT null UNKNOWN

Page 54: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 53 - 과정명 : JPA와 Hibernate

조건식과 연산자 (5/5)

컬렉션

컬렉션의 IS NOT NULL 체크가 불가능하여, IS [NOT] EMPTY를 사용함

컬렉션 EMPTY 체크 예,

WHERE c.items IS EMPTY

JPQL에서의 다음 표현이,

SQL의 다음 표현으로 변환됨

SELECT c

FROM Category c

WHERE c.items IS EMPTY

SELECT

c.CATEGORY_ID, c.CATEGORY_NAME, c.CREATE_DATE,

c.CREATED_BY, c.PARENT_ID

FROM CATEGORIES c

WHERE (

(SELECT COUNT(*)

FROM CATEGORIES_ITEMS ci, ITEMS i

WHERE (

(ci.CATEGORY_ID = c.CATEGORY_ID) AND

(i.ITEM_ID = ci.ITEM_ID))) = 0)

Page 55: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 54 - 과정명 : JPA와 Hibernate

JPQL 함수 사용 (1/2)

개요

JPQL은 문자열과 산술(arithmetic) 연산을 위한 내장 함수를 제공함

이 함수는 WHERE절이나 HAVING 절에서 사용할 수 있음

문자열 함수

질의 결과 필터링에 사용함

문자열 함수 설명

CONCAT(string1, string2) 두 문자열 값을 합쳐서 리턴함

SUBSTRING(string, position, length) position부터 length까지의 부분 문자열을 리턴함

TRIM([LEADING|TRAILING|BOTH] [trim_character] FROM] string_to_trimmed)

지정된 문자열을 새로운 길이로 정리함. 정리(trimming)은 LEADING, TRAILING, 또는 BOTH 끝단에서. 정리 문자가 없으면 기본으로 스페이스임

LOWER(string) 문자열을 소문자로 변환

UPPER(string) 문자열을 대문자로 변환

LENGTH(string) 문자열의 길이를 리턴함

LOCATE(searchString, sringToBeSearched[initialPosition])

주어진 문자열의 위치를 리턴함. initialPosition을 주지 않으면 1로부 검색을 시작함

Page 56: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 55 - 과정명 : JPA와 Hibernate

JPQL 함수 사용 (2/2)

문자열 함수 (계속)

합친 문자열을 비교하는 예,

WHERE CONCAT(u.firstName, u.lastName) = ‘ViperAdmin’

하위 문자열을 비교하는 예,

WHERE SUBSTRING(u.lastName, 1, 3) = ‘VIP’

산술 함수

CRUD 오퍼레이션에 계산은 별로 쓰이지 않음

보고 목적으로 산술 함수를 사용하면 매우 유용함

다음 함수는 WHERE 절이나 HAVING 절에서 사용함

SIZE의 예, WHERE SIZE(c.items) = 5

산술 함수 설명

ABS(simple_arithmetic_expression) 절대값을 리턴함

SQRT(simple_arithmetic_expression) 제곱근을 리턴함

MOD(num, div) 정수값 리턴

SIZE(collection_value_path_expression) 컬렉션의 항목 개수를 리턴함

Page 57: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 56 - 과정명 : JPA와 Hibernate

SELECT 절 사용

개요

SELECT절은 질의 결과를 나타냄

SELECT절의 구문

• SELECT [DISTINCT] expression1, expression2, .... expressionN

• expression은 단일 값임, 컬렉션 값 경로 표현식은 불가능함

SELECT 절의 예,

중복 데이터를 허용하지 않는 예,

생성자 표현식 사용

하나 이상의 자바 인스턴스를 리턴하기 위해 생성자 사용이 가능함

SELECT c.categoryName, c.createdBy

FROM Category c

SELECT DISTINCT c.categoryName, c.createdBy

FROM Category c

SELECT NEW actionbazaar.persistence.ItemReport (c.categoryID, c.createdBy)

FROM Category

WHERE categoryId.createdBy = :userName

Page 58: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 57 - 과정명 : JPA와 Hibernate

조합(Aggregation) 사용 (1/2)

조합은 엔티티 컬렉션을 다루는 보고서 질의를 작성할 때 유용함

조합 함수

JPQL은 조합 함수를 제공함, AVG, COUNT, MAX, MIN, SUM

조합함수의 리턴타입

• AVG() 리턴타입은 Double

• COUNT() 리턴타입은 Long

• MAX() 리턴타입은 지속성 필드에 따라 다름

• MIN() 리턴타입은 지속성 필드에 따라 다름

• SUM() 리턴타입은 Long 이나 Double

가격이 가장 높은 값을 찾는 예,

질의 결과 개수를 세는 예,

SELECT MAX(i.itemPrice)

FROM Item i

SELECT COUNT(c)

FROM Category c

Page 59: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 58 - 과정명 : JPA와 Hibernate

조합(Aggregation) 사용 (2/2)

GROUP BY와 HAVING으로 묶음짓기

특정 필드를 기준으로 데이터를 묶음지을 필요가 있음

User와 Category 간에 일대다 관계가 있을 때, Category 인스턴스를 user기준으로 묶음

위의 예에서, Category 엔티티를 다섯 개 이상 가진 사용자만으로 제한한 예,

WHERE 절 추가 한 예,

SELECT c.user, COUNT(c.categoryId)

FROM Category c

GROUP BY c.user

SELECT c.user, COUNT(c.categoryId)

FROM Category c

GROUP BY c.user

HAVING COUNT(c.categoryId) > 5

SELECT c.user, COUNT(c.categoryId)

FROM Category c

WHERE c.createDate is BETWEEN :date1 and :date2

GROUP BY c.user

HAVING COUNT(c.categoryId) > 5

Page 60: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 59 - 과정명 : JPA와 Hibernate

질의 결과 정렬

ORDER BY 절

검색 결과 값이나 객체를 정렬할 때 사용함

ORDER BY 절 구문, ASC 이 기본값임

ORDER BY path_expression1 [ASC | DESC], ... path_expressionN [ASC | DESC]

카테고리 이름으로 오름차순으로 정렬한 예,

오름차순과 내림차순을 각각 지정한 예,

WHERE 절이 있을 경우, 먼저 WHERE 절에 의해 필터링 된 다음, 정렬함

SELECT c

FROM Category c

ORDER BY c.categoryName ASC

SELECT c.categoryName, c.createDate

FROM Category c

ORDER BY c.categoryName ASC, c.createDate DESC

Page 61: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 60 - 과정명 : JPA와 Hibernate

하위-질의 사용 (1/3)

하위-질의(subquery)

하위-질의는 질의 속의 질의임

WHERE 절이나 HAVING 절에서 하위-질의를 사용할 수 있음

JPQL에서는 SQL과는 달리 FROM 절에서는 하위-질의를 사용할 수 없음

하위-질의가 먼저 실행되고 본 질의가 다음으로 실행됨

하위-질의 구문

[NOT] IN / [NOT] EXISTS / ALL / ANY / SOME (하위-질의)

IN에서 하위-질의

IN절은 리스트 값에서 하나의 값이 포함되어 있는지를 평가함

IN에서 하위-질의 예,

SELECT i

FROM Item i

WHERE i.user IN (SELECT c.user

FROM Category c

WHERE c.categoryName LIKE :name)

Page 62: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 61 - 과정명 : JPA와 Hibernate

하위-질의 사용 (2/3)

EXISTS

하위-질의가 어떤 결과 세트를 포함하는 지 확인 함

EXISTS 절의 예,

EXISTS 절은 IN 연산자와 동일함

테이블이 대용량 데이터를 가지고 있을 경우, IN 보다는 EXISTS 사용을 권장함

DB는 EXISTS를 사용할 때 더 효율적으로 처리함

ANY, ALL, SOME

IN 연산자 사용과 유사함

산술 연산자와 함께 사용할 수 있음, =, >, >=, <, <=, <>

SELECT i

FROM Item i

WHERE EXISTS (SELECT c

FROM Category c

WHERE c.user = i.user)

Page 63: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 62 - 과정명 : JPA와 Hibernate

하위-질의 사용 (3/3)

ANY, ALL, SOME (계속)

하위-질의와 ALL 연산자의 예,

하위-질의와 ANY 연산자의 예,

SOME은 ANY의 다른 이름

SELECT c

FROM Category c

WHERE c.createDate >= ALL

(SELECT i.createDate

FROM Item i

WHERE i.user = c.user)

SELECT c

FROM Category c

WHERE c.createDate >= ANY

(SELECT i.createDate

FROM Item i

WHERE i.seller = c.user)

Page 64: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 63 - 과정명 : JPA와 Hibernate

엔티티 조인 (1/3)

JOIN 연산자

FROM 절에 엔티티 지정함

WHERE 절에 조인 조건을 지정함

두 엔티티는 관계나 임의의 지속성 필드를 기반으로 연결(join)함

내부 조인: 관계를 이용하여 Category와 Item을 조인하고 조인 조건에 일치하는 엔티티만을 검색함

외부 조인: 조인 조건에 일치하는 결과 뿐 아니라 다른 쪽의 엔티티에 일치하지 않는 엔티티 역시 검색함, 즉 Item과 일치하지 않더라도 Category의 모든 인스턴스를 검색함

쎄타(Theta) 조인

관계 보다는 임의의 지속성이나 관계 필드를 기반으로 연결함

Category의 rating 필드가 DELUXE, GOLD, STANDARD, PREMIUM 값을 가짐

Item의 star 필드 역시 DELUXE, GOLD, STANDARD, PREMIUM 값을 가짐

이 두 엔티티를 쎄타 조인을 걸면, SELECT i

FROM Item i, Category c

WHERE i.star = c.rating

Page 65: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 64 - 과정명 : JPA와 Hibernate

엔티티 조인 (2/3)

관계 조인

가장 흔한 형태의 조인임

관계를 바탕으로 둘 또는 그 이상의 엔티티를 연결함

Category와 User는 다대일 관계를 가짐, 특정 범주에 속하는 모든 사용자 검색 예,

외부 조인

엔티티 간의 연관관계가 선택적일 때, 조인 조건에 맞지 않는 추가 엔티티를 검색할 수 있음

보고서 작성에 매우 유용함

Category를 가지지 않는 User도 있을 경우의 예,

SELECT u

FROM User u INNER JOIN u.Category c INNER 절은 선택사항임

WHERE u.userId LIKE ?1

SELECT u

FROM User u LEFT OUTER JOIN u.Category c

WHERE u.userId like ?1

Page 66: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 65 - 과정명 : JPA와 Hibernate

엔티티 조인 (3/3)

페치(fetch) 조인

특정 엔티티를 위한 질의를 하면서, 동시에 연관 엔티티도 동시에 검색할 수 있음

Bid를 검색할 때, 연관된 Bidder의 인스턴스를 로드하고 초기화 하는 예,

관계에 대해 지연 로드로 설정된 상황, 특정 질의에서 연관 엔티티를 즉시 로드할 때

페치 조인은 외부,내부 조인과 함께 사용할 수 있음

SELECT b

FROM Bid b FETCH JOIN b.bidder

WHERE b.bidDate >= :bidDate

Page 67: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 66 - 과정명 : JPA와 Hibernate

대량 갱신과 삭제

개요

연말에 사용자의 상태 값을 모두 G(old)로 변경하는 예,

특정 조건에 맞는 사용자를 모두 삭제하는 예,

대량 갱신과 삭제는 여러 함정이 있으므로 반드시 별도의 트랜잭션으로 실행해야 함

DB 오퍼레이션으로 바로 변환되므로 관리 엔티티와 DB 간 불일치 발생 가능함

UPDATE User u

SET u.status = 'G'

WHERE u.numTrades >=?1

@PersistenceContext em;

. . .

// start transaction

Query query = em.createQuery("DELETE USER u WHERE u.status = :status ");

query.setParameter("status", 'GOLD');

int results = query.executeUpdate();

//end transaction

Page 68: 데이터 접근프레임워크 (JPA와 Hibernate)etna.emro.co.kr/wp-content/uploads/2014/08/JPA_3.pdf · 2014. 8. 24. · 데이터 접근프레임워크 (JPA와 Hibernate) 교육기간

- 67 - 과정명 : SQL기초와 MyBatis – SQL/MyBatis

넥스트리소프트(주) 박석재 수석 ([email protected]) 임병인 수석 ([email protected])