Whiteship's Note


Hibernate Core VS JPA

Hibernate/Chapter 5 : 2008.02.04 17:39


Hibernate JPA
네 가지 상속 맵핑 전략을 제공하고, 상속 전략을 혼용하는 것이 가능하다. 네 가지 맵핑 전략을 표준화 했다. 이 중에선 Table Per Class Hierarchy와 Table Per Subclass만 JPA 호환 필수요소다.
영속성 대상이 되는 클래스의 상위 클래스는 abstract class나 interface도 될 수 있다. abstract class만 이식 가능하다.
Value Type을 위한 유연한 내장 타입과 컴버터를 제공한다. 표준화된 방법으로 맵핑 타입을 자동으로 찾아 준다. 커스텀 타입을 찾을 때는 하이버네이트 확장 애노테이션을 사용한다.
막강한 타입 확장 시스템 Enum을 위한 내장 타입 표준이 필요하다.

'Hibernate > Chapter 5' 카테고리의 다른 글

Hibernate Core VS JPA  (0) 2008.02.04
Enum Type 맵핑하기 - 실습  (0) 2008.02.04
Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
top

Write a comment.


상속 맵핑 전략 선택하기

Hibernate/Chapter 5 : 2008.02.01 21:40


맵핑 전략

  • 다형적인 관계나 쿼리가 필요하지 ㅇ낳다면, Table Per Concrete Class를 사용하라. 즉, 상위 타입으로 객체들을 가져다 쓰지 않을거라면...
  • 다형적인 관계나 쿼리가 필요하고, 하위 클래스들의 속성이 몇 개 되지 않는 다면, Table Per Class Hierarchy를 사용하라.
  • 다형적인 관계나 쿼리가 필요하고, 하위 클래스들에 속성들이 많다면 Table Per SubClass를 사용하라.

특징

  • 간단한 경우에는 Table Per Class Hierarchy를 사용하라. 그 다음에 좀 더 복잡한 경우에 Table Per Subclass를 고려하라. 하지만 그렇게 하기 전에 상속구조를 Deligation으로 대체할 수 없을지 고민해 봐라.
  • 하이버네이트가 도메인과 관계형 모델의 버퍼 역할을 해주긴 하지만, 그렇다고 해서 Persistence Concern을 몰라도 된다는 뜻은 아니다.

'Hibernate > Chapter 5' 카테고리의 다른 글

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top

Write a comment.


상속 맵핑 전략 혼용하기

Hibernate/Chapter 5 : 2008.02.01 21:40


특징

  • 특정 하위 클래스에 대한 맵핑 정랸글 변경할 수 있다.
  • 하이버네이트가 2차 테이블에서 속성들을 가져오도록 설정한다.

맵핑하기

  • 기본으로 Table Per Class Hierachy를 사용하고 특정 하위 클래스만 Table Per Sub Class 사용하기.
  • @SecondaryTable 애노테이션 사용하기.
  • 2차 테이블에는 모든 속성을 명시해 주어야 한다.

'Hibernate > Chapter 5' 카테고리의 다른 글

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top

Write a comment.


Table per subclass

Hibernate/Chapter 5 : 2008.02.01 21:39


특징

  • 영속화 할 필드를 가진 모든 클래스의 테이블을 만든다.
  • 상위 클래스의 주키를 하위 클래스의 주키이자 외례키로 사용한다.
  • Join을 사용해서 상위 타입으로 하위 타입의 객체를 가져올 수 있다.

장점

  • 정규화를 할 수 있다.
  • 스키마 개선과 무결성 제약 정의가 간단하다.
  • 다형성은 특정 하위 클래스로의 외례키 참조로 가능하다.
  • 구분자 컬럼 필요없다.

단점

  • 복잡한 클래스 구조에서는 성능이 안 좋을 수 있다.

맵핑하기

  • 상위 클래스
@Entity
@Table(name="BILLING_DETAIL")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class BillingDetails {
  • 하위 클래스
@Entity
public class CreditCard extends BillingDetails {

or

@Entity
@PrimaryKeyJoinColumn(name="CREDIIT_CARD_ID")
public class CreditCard extends BillingDetails {

쿼리 분석

  • 상위 타입으로 요청할 때는 left outter join
select billingdet0_.BILLING_DETAILS_ID as BILLING1_0_, billingdet0_.OWNER as OWNER0_, 
billingdet0_1_.ACCOUNT as ACCOUNT1_, billingdet0_2_.CC_NUMBER as CC2_2_,
case
when billingdet0_1_.BILLING_DETAILS_ID is not null then 1
when billingdet0_2_.BILLING_DETAILS_ID is not null then 2
when billingdet0_.BILLING_DETAILS_ID is not null then 0 end as clazz_
from BILLING_DETAIL billingdet0_
left outer join BankAccount billingdet0_1_ on
billingdet0_.BILLING_DETAILS_ID=billingdet0_1_.BILLING_DETAILS_ID
left outer join CreditCard billingdet0_2_ on
billingdet0_.BILLING_DETAILS_ID=billingdet0_2_.BILLING_DETAILS_ID
  • 하위 타입으로 요청할 때는 inner join.
select bankaccoun0_.BILLING_DETAILS_ID as BILLING1_0_, bankaccoun0_1_.OWNER as OWNER0_, 
bankaccoun0_.ACCOUNT as ACCOUNT1_
from BankAccount bankaccoun0_
inner join BILLING_DETAIL bankaccoun0_1_ on
bankaccoun0_.BILLING_DETAILS_ID=bankaccoun0_1_.BILLING_DETAILS_ID

'Hibernate > Chapter 5' 카테고리의 다른 글

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top

Write a comment.


Table per class hierarchy

Hibernate/Chapter 5 : 2008.02.01 21:38


특징

  • 전체 상속 구조 하나를 단일 클래스로 맵핑한다.
  • 하위 클래스의 객체들은 타입 구분자 Type Discriminator 컬럼의 값으로 구분한다.
  • 구분자를 추가할 수 없는 상황에서는 formula를 사용한다. SQL의 CASE/WHERN

장점

  • 다형적이거나 그렇지 않은 쿼리를 수행하는 성능이 좋다. <- 조인이나 Union을 하지 않으니까.
  • 구현하기도 간편하다. <- 스키마가 간단하니까.

단점

  • 하위 클래스의 속성들은 반드시 nullable이어야 한다.
  • 정규화가 되지 않는다. 키가 아닌 값에 종속성에 생기므로, 3차 정규화를 깨트렸다. DBA가 싫어할 것이다.

맵핑하기

  • 상위 클래스(discriminator 사용)
@Entity
@Table(name="BILLING_DETAIL")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="BILLING_DETAILS_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class BillingDetails {

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name = "BILLING_DETAILS_ID")
private Long id = null;

@Column(name = "OWNER", nullable = false)
private String owner;
  • 상위 클래스(formula 사용)
@Entity
@Table(name="BILLING_DETAIL")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorFormula("case when CC_NUMBER is not null then 'CC' else 'BA' end")
public abstract class BillingDetails {
  • 하위 클래스
@Entity
@DiscriminatorValue("CC")
public class CreditCard extends BillingDetails {

@Column(name = "CC_NUMBER")
private String number;

쿼리 분석

  • 상위 타입으로 가져올 때는 조건 없이 모든 컬럼 가져온다.
List<BillingDetails> bdList = session.createQuery("from BillingDetails").list();

select billingdet0_.BILLING_DETAILS_ID as BILLING2_0_, billingdet0_.OWNER as OWNER0_, billingdet0_.ACCOUNT as ACCOUNT0_, billingdet0_.CC_NUMBER as CC5_0_, billingdet0_.BILLING_DETAILS_TYPE as BILLING1_0_
from BILLING_DETAIL billingdet0_
  • 하위 타입으로 가져올 때는 Discriminator 사용해서 조건을 준다.
List<CreditCard> bdList = session.createQuery("from CreditCard").list();

select creditcard0_.BILLING_DETAILS_ID as BILLING2_0_, creditcard0_.OWNER as OWNER0_, creditcard0_.CC_NUMBER as CC5_0_
from BILLING_DETAIL creditcard0_
where creditcard0_.BILLING_DETAILS_TYPE='CC'

'Hibernate > Chapter 5' 카테고리의 다른 글

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top

Write a comment.


Table per concrete class

Hibernate/Chapter 5 : 2008.02.01 21:37


특징

  • 상위 클래스에 하위 클래스들을 Union으로 포함하여 가지고 있게 설정한다.
  • JPA에서 TABLE_PER_CLASS는 필수 구현사항이 아니다. 따라서 밴더마다 다를 수 있다.
  • Hibernate의 polymorphic loader engine이 쿼리의 성능 걱정을 덜어 줄 것이다.
  • 하위 클래스들이 상위 클래스에 정의한 하나의 주키를 공유한다.
  • 주키 생성 타입을 identity로 하면 안 된다. AUTO로 설정했을 때 주의할 것. 안 그러면 Cannot use identity column key generation with <union-subclass> mapping. 이 에러를 만나게 될 것이다.

장점

  • 다형적인 관계를 다룰 수 있다. UNION 쿼리를 사용해서 단일 테이블을 관계 맵핑 처럼 사용할 것이다.(?? 7.3 참조)
  • 지금까지는 SQL 스키마는 전혀 상속을 위한 추가 설정이 필요하지 않았다. 정규화도 잘 되었고 추가적인 외례키를 필요도 하지도 않았다.

맵핑하기

  • 상위 클래스
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BillingDetails {

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name = "BILLING_DETAILS_ID")
private Long id = null;

@Column(name = "OWNER", nullable = false)
private String owner;
  • 하위 클래스
@Entity
@Table(name="CREDIT_CARD")
public class CreditCard extends BillingDetails {

@Column(name = "NUMBER", nullable = false)
private String number;

쿼리 분석

select BILLING_DETAILS_ID, OWNER, ACCOUNT, NUMBER, clazz_
from
( select OWNER, ACCOUNT, null as NUMBER, BILLING_DETAILS_ID, 1 as clazz_ from BANK_ACCOUNT
union
select OWNER, null as ACCOUNT, NUMBER, BILLING_DETAILS_ID, 2 as clazz_ from CREDIT_CARD )
  • clazz_ 컬럼: 컬렉션에서 하위 타입의 객체를 만들 때 구분하기 위해서 사용.
  • null 인 컬럼들(BANK_ACCOUNT의 NUMBER, CREDIT_CARD의 ACCOUNT): UNION을 사용하기 위해서는 같은 컬럼을 가지고 있어야 한다.

'Hibernate > Chapter 5' 카테고리의 다른 글

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top

Write a comment.


Table per connrete class with implicit polymorphism

Hibernate/Chapter 5 : 2008.02.01 21:37


특징

  • 모든 구현 클래스 하나 당 하나의 테이블로 표현한다.
  • 상속 받은 속성들도 테이블의 컬럼으로 맵핑한다.

문제점

  • 다형적인 관계를 잘 지원하지 못해. 왜? 상위 클래스와 관계를 맺고 있는 클래스가 하위 클래스를 참조해야 한다면, 이 클래스가 가져야 할 하위 클래스의 외례키는 두 개의 하위 클래스 모두의 주키를 대변해야 할 텐데, 이런게 테이블에서는 불가능하다.
  • 다형적인 쿼리(특정 상위 클래스 타입에 해당하는 모든 객체를 요구하는 쿼리)도 역시 문제가 된다. 왜? 각각의 하위 클래스마다 쿼리를 수행해서 데이터를 가져와야 한다.
  • 약간 다른 여러 테이블이 같은 정보를 공유하고 있다. 이게 왜 문제가 될까? 스키마를 점점 복잡하게 만든다. 예를들어, 상위 타입의 속성 하나를 변경하면 그것을 상속하나 모든 테이블을 수정해야 한다. 모든 하위 클래스에 무결성 제약을 적용하기도 힘들다.
  • 변경될 가능성이 거의 없고, 다형성이 별로 필요 없는, 최상위 레벨의 상속구조에서 사용하기를 권장한다.
  • JPA는 다형적인 쿼리를 지원하지 않는다. 하지만 Hibernate의 쿼리 인터페이스는 지원한다.

해결책

  • SQL의 UNION 함수를 사용해서 위에서 발생한 다형적인 쿼리와 관계에 대한 이슈 대부분을 제거할 수 있다.

맵핑하기

  • 하위 클래스는 @Entity로 맵핑하기
@Entity
@AttributeOverride(name = "owner", column = @Column(name = "CC_OWNER", nullable = false))
public class CreditCard extends BillingDetails {

@Id
@GeneratedValue
@Column(name = "CREDIT_CARD_ID")
private Long id = null;

@Column(name = "NUMBER", nullable = false)
private String number;
  • 상위 클래스는 @MappedSuperclass로 맵핑하기
@MappedSuperclass
public class BillingDetails {

@Column(name = "OWNER", nullable = false)
private String owner;

'Hibernate > Chapter 5' 카테고리의 다른 글

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top

Write a comment.