Whiteship's Note


상속 맵핑 전략 혼용하기

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


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


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


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


기본 속성 맵핑하기- 실습

Hibernate/Chapter 4 : 2008.01.22 09:41


기본값 설정하는 방법을 테스트합니다.
- @Column의 columnDefinition 속성을 사용해서 column을 만들 때 사용할 공식을 사용할 수 있습니다.
- 하이버의 @GenerationTime 애노테이션을 사용해서 기본값이나 생성되는 값을 언제 생성할 지 설정할 수 있습니다.

1. 테스트 코드

    @Test
    public void add() throws Exception {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();

        Member member = new Member();
        member.setName("썬");

        session.save(member);
        session.flush();

        transaction.rollback();
        session.close();
        assertNotNull(member.getId());
        assertEquals(new Integer(1), member.getDefaultNum());
    }

2. 결과 쿼리

Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into Member (name, id) values (?, ?)
Hibernate: select member_.defaultNum as defaultNum0_ from Member member_ where member_.id=?

3. Persistent Class

@Entity
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    @Column(columnDefinition = "number(10,2) default '1'")
    @org.hibernate.annotations.Generated(org.hibernate.annotations.GenerationTime.INSERT)
    private Integer defaultNum;

    ...

}

위 테스트 코드에서 flush를 하지 않으면 시퀀스만 가져오고 insertion은 이뤄지지 않습니다. insertion을 안하기 때문에 db가 생성하는 기본값을 가져오기 위해 발생하는 세번째 쿼리도 실행하지 않습니다. 따라서 다음의 SQL 한 문장만 실행합니다.

Hibernate: select hibernate_sequence.nextval from dual

참조 : 4.4.1 Mapping basic properties/Generated and default property values




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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


컴포넌트 맵핑하기

Hibernate/Chapter 4 : 2008.01.20 13:38


특징

  • 자바 객체에서 Value-type과 Entity를 구분지을 수 있는것은 식별자 속성 뿐이다.
  • 컴포넌트와 Entity 간의 양방향 관계를 설정할 수 있다.
  • 컴포넌트가 다른 컴포넌트나 Entity를 가지고 있을 수 있다.
    • This flexibility is the foundation of Hibernate's support for finegrained object models.

설정하기

  • 컴포넌트에는 @Embeddable Entity의 속성에는 @Embedded 사용하기
  • @org.hibernate.annotations.Parent 애노테이션으로 컴포넌트에서 back-pointer 프로퍼티 사용 가능.
  • if you store a component object with all null property values, Hibernate returns a null component when the owning entity object is retrieved from the database.
컴포넌트 사용하기
@Entity
@Table(name = "USERS")
public class User {
@Embedded
private Address homeAddress;


}
컴포넌트 클래스 정의하기
@Embeddable
public class Address {

@Column(name="ADDRESS_STREET", nullable=false)
private String street;

@Column(name="ADDRESS_ZIPCODE", nullable=false)
private String zipcode;

@Column(name="ADDRESS_CITY", nullable=false)
private String city;

}
  • 컴포넌트를 사용하는 쪽에서 컴포넌트의 컬럼 정의를 재정의 할 수도 있다.
  • 단점
    • First,shared references, as for all value types, aren't possible. -> 이건 value-type 이니까 당연히 그래야 하는거 아닌가.
    • Second, there is no elegant way to represent a null reference to an Address. -> 흠.. new Address()를 항상 가지고 있어야겠군.

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


기본 속성 맵핑하기

Hibernate/Chapter 4 : 2008.01.20 13:35


특징

  • @Transient 애노테이션을 붙이거나 자바의 transient 키워드를 사용하지 않으면 기본으로 전부 Persistent 대상으로 인식한다.
  • 애노테이션을 붙이지 않으면 다음과 같은 규칙이 적용된다.
    • JDK가 제공하는 타입일 경우에 자동으로 Persistent 대상이 된다.
    • 그렇지 않고, 속성의 타입에 해당하는 클래스에 @Embeddable 애노테이션이 붙어있는 경우, 컴포넌트를 가지고 있는 형태로 맵핑된다.
    • 그렇지도 않고, 속성의 타입이 Serializable 인터페이스를 구현한 경우, 직렬화된 형태로 DB에 저장된다. (이러길 원치 않을 것이다.)

설정하기

  • Chapter 17에서 하이버네이트 애노테이션으로 DDL을 작성하거나 동적으로 검증하는 기능에 대해 다룬다.
  • 클래스 속성에 접근하는 방법은 @Id 애노테이션이 붙어있는 위치가 기본 방법으로 설정 된다.(JPA)
  • 하이버네이트는 이 기본 방법을 변경할 수 있는 기능을 제공한다. @org.hibernate.annotations.AccessType(<strategy>)
    • 클래스에 AccessType 애노테이션을 사용하면, @Id로 인해 설정되는 접근 전략을 무시하며, 해당 클래스의 필드나 메서드에 붙어있는 모든 애노테이션들은 AccessType에서 정의한 접근 전략을 따른다.
    • 기본 상태이거나 필드 접근인 상태에서 @AccessType("property")를 필드 위에 붙여주면, 해당 속성을 accessor 메소드들을 이용해서 접근한다.
    • 기본 상태이거나 Accessor 접근이 상태에서 @AccessType("field")를 getter 위에 붙여주면, 해당 속성은 필드에 바로 접근한다.
    • @Embedded 클래스는 자신을 가지고 있는 쪽 클래스의 접근 방법을 따른다.
    • @MappedSuperclass 클래스는 맵핑 된 클래스의 접근 방법을 따른다.
  • noop 방식: "virtual" property in HQL queries. to use the database column in HQL queries only.
  • 마음에 드는게 없으면 org.hibernate.property.PropertyAccessor 인터페이스 구현해서 직접 만들어 됨.
    • 사용할 때는 @AccessType 애노테이션의 access 속성에 패키지 이름을 붙인 클래스 이름을 써주면 돼.

계산이 필요한 속성

  • 맵핑되는 컬럼은 없다.
  • @Fomula 애노테이션 사용하기
필드에서 계산된 속성 사용하기
@org.hibernate.annotations.Formula("TOTAL + TAX_RATE * TOTAL")
public BigDecimal getTotalIncludingTax() {
return totalIncludingTax;
}
  • SQL 함수도 사용할 수 있다.

h1, DB에서 생성된 값과 기본 값

  • public 세터를 만들지 말아라.
  • @Generated 애노테이션 사용하기
DB에서 생성된 값 사용하기
@Column(updatable = false, insertable = false)
@org.hibernate.annotations.Generated(
org.hibernate.annotations.GenerationTime.ALWAYS
)
private Date lastModified;
  • 기본값이 설정되도록 하려면 flush 해야한다.
  • columnDefinition 속성으로 기본값 설정하기
기본값 설정하기
@Column(name = "INITIAL_PRICE",
columnDefinition = "number(10,2) default '1'")
@org.hibernate.annotations.Generated(
org.hibernate.annotations.GenerationTime.INSERT
)
private BigDecimal initalPrice;
  • columnDefinition: complete properties for the column DDL, with datatype and all constraints.
    • DDL customization은 8장에서 다룬다.

모르는 것

  • @MappedSuperclass는 뭔가?

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


작명 지침 사용하기

Hibernate/Chapter 4 : 2008.01.20 13:29


특징

  • Hibernate provides a feature that allows you to enforce naming standards automatically.

설정하기

  • NamingStrategy 인터페이스 구현하기
  • ImprovedNamingStrategy 클래스 상속받아서 구현하기
네임스페이스 등록하기
import org.hibernate.cfg.ImprovedNamingStrategy;
import org.hibernate.util.StringHelper;

public class CENamingStrategy extends ImprovedNamingStrategy {
public String classToTableName(String className) {
return StringHelper.unqualify(className);
}

public String propertyToColumnName(String propertyName) {
return propertyName;
}

public String tableName(String tableName) {
return "CE_" + tableName;
}

public String columnName(String columnName) {
return columnName;
}

public String propertyToTableName(String className, String propertyName) {
return "CE_" + classToTableName(className) + '_'
+ propertyToColumnName(propertyName);
}
}
  • classToTableName(): <class> 맵핑에서 table 속성에 값을 입력하지 않았을 때 호출.
  • propertyToColumnName(): 명시적인 column 이름을 설정하지 않았을 때 호출.
  • tableName(), columnName(): 명시적으로 이름을 설정했을 때 호출.
  • 동적으로 설정을 바꿀 수 있음.
동적으로 네임스페이스 바꾸기
Configuration cfg = new Configuration();
cfg.setNamingStrategy( new CENamingStrategy() );
SessionFactory sessionFactory sf =
cfg.configure().buildSessionFactory();

모르는 것

  • SessionFactory 설정할 때 구현한 클래스를 등록해 주면 되는건가?

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


SQL문에 따옴표 사용하기

Hibernate/Chapter 4 : 2008.01.20 13:27


특징

  • Hibernate doesn't quote table and column names in the generated SQL.
  • 대소문자를 구분하거나, 특수 문자를 사용하는 기존 DB의 경우 하이버네이트가 자동으로 생성하는 컬럼이나 테이블이름을 인식하지 못할 수도 있다.

설정하기

역따옴표 사용하기
<property name="description"
column="`DESCRIPTION`"/>
  • If you quote a table or column name with backticks in the mapping document, Hibernate always quotes this identifier in the generated SQL.
  • 애노테이션에서도 설정할 수 있으나, 하이버네이트 @Column 애노테이션을 사용하야 한다. JPA에서는 지원하지 않는다.

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


패키지 이름 설정하기

Hibernate/Chapter 4 : 2008.01.20 13:24


특징

  • (XML 설정 파일 이용 시)
  • Persistent 클래스 등록할 때, 패키지 이름까지 붙어있는 이름을 등록해야 한다.
  • 같은 패키지에 위치한 여러 클래스들을 등록할 때 패키지 이름을 매번 붙여주기가 귀찮다.

설정하기

기본 패키지 설정하기
<hibernate-mapping package="auction.model">
<classname="Item" table="ITEM">
...
</class>
</hibernate-mapping>
  • 애노테이션에서는 이런 설정이 필요 없겠지. 해당 클래스에 가서 직접 붙여주는데...

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


쿼리에서 사용할 Entity 이름 설정하기

Hibernate/Chapter 4 : 2008.01.20 13:24


특징

  • 기본으로 모든 클래스 이름들이 자동으로 HQL의 네임스페이스로 import 된다.
  • 즉, HQL에서 패키지 이름을 제외한 클래스 이름을 사용할 수 있다.
  • 서로 다른 패키지에 같은 이름의 클래스가 존재한다면, auto-import를 끄거나, 명시적으로 네임스페이스를 설정해야 한다.

설정하기

HQL에서 사용할 네임스페이스 설정하기
@Entity(name="AuctionItem")
public class Item {

}

모르는 것

  • 애노테이션을 사용해서 auto-import를 끄는 방법은?
  • auto-import를 끄면 패키지 이름이 붙어있는 클래스 이름을 네임스페이스로 사용하는 건가?

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


Immutable Entity 만들기

Hibernate/Chapter 4 : 2008.01.20 13:22


특징

  • 변하지 않아야 할 Persistent 객체가 있을 수 있다.
  • 이런 Persistent 클래스에는 필드로 직접 접근하도록 설정하고, accessor 메소드들을 만들지 않으면 된다.

설정하기

immutable entity 설정하기
@Entity
@org.hibernate.annotations.Entity(mutable=false)
@org.hibernate.annotations.AccessType("field")
public class Bid {

}
  • @AccessType은 하이버네이트가 Pesistent 클래스에 접근하는 방법을 표시한다.
  • 클래스, 메소드, 필드 위에 붙여서 좀 더 세밀한 설정이 가능하다.

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


동적 SQL 생성

Hibernate/Chapter 4 : 2008.01.20 13:21


특징

  • 기본으로 하이버네이트가 시작할 때, 각각의 Persistent 클래스와 관련된 CRUD 쿼리를 생성한다.
  • UPDATE 문은 모든 필드를 수정하도록 작성되어 있다.
  • Sometimes you can avoid generating any UPDATE statement, if the persistent class is mapped immutable.

설정하기

동적으로 쿼리 생성하도록 설정
@Entity
@org.hibernate.annotations.Entity(dynamicInsert=true, dynamicUpdate=true)
public class Category {
...
}
  • 아래에 있는 하이버네이트의 Entity 애노테이션이 위에 있는 Entity를 확장한다.

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


주키 정하기

Hibernate/Chapter 4 : 2008.01.14 17:04


Natural key vs Surrgate key

  • 후보키candidate key는 다음과 같은 특징을 가진다.
    • NULL 값을 갖지 않는다.
    • 유일한 값을 갖는다.
    • 값이 절대로 변하지 않는다.
  • A natural key is a key with business meaning: an attribute or combination of attributes that is unique by virtue of its business semantics.
  • Natural key를 주키로 사용해 왔지만, 다음과 같은 문제가 있다.
    • 변하지 않고, 고유하면서, 필수인 값을 찾기가 어렵다. 주키 값을 변경하는 작업은 완전 빡쎄며, 인덱스로 사용하기도 적절하지 않다.
    • 주로 복합키로 구성되는데, 이 것들이 보통 쿼리 작성, 스키마 수정, 유지보수를 어렵게 한다.
  • 그래서 Surrogate key 사용을 추천한다.
    • Surrogate keys have no business meaning—they're unique values generated by the database or application.

key generator 선택하기

  • Hibernate has several built-in identifier-generation strategies.
Generator name JPA Generation Type Option 설명
native AUTO   사용하는 DB에 따라서 sequence, hilo, identity를 알아서 선택함. 설정의 이식성을 고려한다면, 이 설정을 사용할 것.
identity IDENTITY   DB2, MySQL, MS SQL Server, Sybase, HypersonicSQL에 있는 identity 컬럼을 지원한다. long, short, int 타입의 값을 반환함.
sequence SEQUENCE sequence, parameters DB2, PostgreSQL, Oracle, SAP DB, Mckoi에서 sequence를 생성한다. long, short, int 타입의 값을 반환함. sequence 옵션을 사용해서 시퀀스의 이름을 설정할 수 있고, DDL에 추가할 시퀀스를 만들 때 필요한 추가 세팅이 필요할 때 parameters를 사용함.
increment     하이버네이트가 동작하면서 테이블의 주키 컬럼 값 중에 최대값을 읽은 다음 새로운 레코드를 추가할 때, 그 값을 1씩 증가시킴. 단일 서버에서 DB에 독립적으로 접근하는 경우 외에는 사용하지 말아라.
hilo   table, column, max_lo A high/low algorithm is an efficient way to generate identifiers of type long, given a table and column as a source of high values.
seqhilo   sequence, parameters, max_lo named database sequence에서 high 값을 걷는 것을 빼고 hilo와 동일하다.
  TABLE table, catalog, schema, pkColumnName, valueColumnName, pkColumnValue, allocationSize TABLE relies on a database table that holds the lastgenerated integer primary key value, and each generator is mapped to one row in this table.
uuid.hex   separator This generator is a 128-bit UUID (an algorithm that generates identifiers of type string, unique within a network).
guid     This generator provides a database-generated globally unique identifier string on MySQL and SQL Server.
select   key This generator retrieves a primary key assigned by a database trigger by selecting the row by some unique key and retrieving the primary key value
하이버네이트 identity generator 사용하기
@Entity
@org.hibernate.annotations.GenericGenerator(name="hibernate-uuid", strategy="uuid")
@Table(name="CATEGORY")
public class Category {

@Id
@GeneratedValue(generator="hibernate-uuid")
@Column(name="CATEGORY_ID")
private Long id;

public Long getId() {
return id;
}

}
  • hibernate-uuid라는 이름으로 uuid 생성기를 사용하는 코드.
  • You aren't limited to the built-in strategies; you can create your own identifier generator by implementing Hibernate's IdentifierGenerator interface.

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

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


XML 도메인 모델

Hibernate/Chapter 3 : 2008.01.13 12:40


특징

  • The XML data model is weak, its type system is complex and underpowered.
  • its data integrity is almost completely procedural.
  • it introduces hierarchical data structures that were outdated decades ago.
  • However, data in XML format is attractive to work with in Java; we have nice tools.

XML로 도메인 모델 뽑아내기

DOM4J로 도메인 모델 뽑아내기
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Element userXML =
(Element) dom4jSession.load(User.class, storedUserId);
  • Element 클래스는 Dom4J API
화면에 출력하기
try {
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter( System.out, format);
writer.write( userXML );
} catch (IOException ex) {
throw new RuntimeException(ex);
}

맵핑할 때 node 속성 사용하기

  • <class> 나 <property> 맵핑에서의 node 속성(node="name")은 XML 엘리먼트의 이름을 정의한다.
  • <property> 맵핑에서 node 속성(node="@name")은 XML 엘리먼트의 속성을 정의한다.
  • <property> 맵핑에서의 node 속성(node="name/@attname")은 name이라는 자식 엘리먼트에 attname이라는 속성을 정의한다.
  • 위의 속성을 사용해서 맵핑하면, 도메인 모델을 표현할 XML을 원하는 형태로 정의할 수 있다.

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

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Map 도메인 모델

Hibernate/Chapter 3 : 2008.01.13 12:05


특징

  • A dynamic domain model is a model that is dynamically typed.
<hibernate-mapping>
<class entity-name="ItemEntity" table="ITEM_ENTITY">
<id name="id" type="long" column="ITEM_ID">
<generator class="native" />
</id>
<property name="initialPrice" type="big_decimal"
column="INIT_PRICE" />
<property name="description" type="string" column="DESCRIPTION" />
<many-to-one name="seller" entity-name="UserEntity"
column="USER_ID" />
</class>
<class entity-name="UserEntity" table="USER_ENTITY">
<id name="id" type="long" column="USER_ID">
<generator class="native" />
</id>
<property name="username" type="string" column="USERNAME" />
<bag name="itemsForSale" inverse="true" cascade="all">
<key column="USER_ID" />
<one-to-many entity-name="ItemEntity" />
</bag>
</class>
</hibernate-mapping>
  • 다수의 도메인 맵핑을 하나의 파일 안에 두고 있다. 자바 클래스를 맵핑하는 것이 아니기 때문에 메타데이터를 어떻게 구성하던 맘대로 하라.
  • <class name="..."> 대신에 <class entity-name="..."> 를 사용했으며, 정적인 도메인 모델과 구분하기 위해 Entity를 접미어로 사용했다.
  • <many-to-one> 와 <one-to-many> 에서 entity-name에 설정한 이름을 사용했다.

동적인 맵 사용하기

동적인 맵 사용 예제
Map user = new HashMap();
user.put("username", "johndoe");

Map item1 = new HashMap();
item1.put("description", "An item for auction");
item1.put("initialPrice", new BigDecimal(99));
item1.put("seller", user);

Map item2 = new HashMap();
item2.put("description", "Another item for auction");
item2.put("initialPrice", new BigDecimal(123));
item2.put("seller", user);

Collection itemsForSale = new ArrayList();
itemsForSale.add(item1);
itemsForSale.add(item2);
user.put("itemsForSale", itemsForSale);

session.save("UserEntity", user);
  • Entity 하나 당 HashMap 객체 하나에 대응한다.
  • ArrayList는 bag을 맵핑하려고 사용했다.
  • Session.save(entity-name, HashMap)를 사용해서 저장했다.
  • cascading에 의해서 user와 user와 연관을 맺고 있는 두 개의 Item 역시 DB에 저장됐다.
  • Set을 사용하면 안 된다. Map은 equals()를 할 때 키값을 가지고 비교하기 때문에, Set을 사용하면 여러 개의 Entity를 넣을 수 없다.

정적인 엔티티 모드와 동적인 엔티티 모드 혼용하기

  • 맵핑할 때, <class name="model.UserPojo" entity-name="UserEntity" table="USER_ENTITY"> 이런식으로 클래스이름과 논리적인 이름을 모두 설정해 준다.
  • Session을 사용할 때는 entity-name을 사용해야 한다.
  • Session의 결과로 받는 값은 기본으로 POJO 객체다.
  • 둘 모두 <property name="default_entity_mode">dynamic-map</property> 를 사용해서 Map을 사용하도록 설정할 수 있다.
  • 특정 세션만 Map을 사용하도록 설정할 수 있다. Session dynamicSession = session.getSession(EntityMode.MAP);
  • Note that you can't link a map with a POJO instance. 당근이지.

하나의 클래스 여러번 맵핑하기

  • 맵핑 할 때 entity-name에 다른 값을 주면, 같은 클래스를 사용해서 서로 다른 테이블로 맵핑할 수 있다.
<hibernate-mapping>
<class name="model.Item" entity-name="ItemAuction"
table="ITEM_AUCTION">
<id name="id" column="ITEM_AUCTION_ID">...</id>
<property name="description" column="DESCRIPTION" />
<property name="initialPrice" column="INIT_PRICE" />
</class>
<class name="model.Item" entity-name="ItemSale" table="ITEM_SALE">
<id name="id" column="ITEM_SALE_ID">...</id>
<property name="description" column="DESCRIPTION" />
<property name="salesPrice" column="SALES_PRICE" />
</class>
</hibernate-mapping>

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

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Entity 표현 대안

Hibernate/Chapter 3 : 2008.01.13 11:59



  • 꼭 POJO로 Entity를 표현하지 않아도 된다.
  • 자바의 HashMap을 사용하여 Entity를 표현할 수 있다.
  • Dom4J를 사용하여 Entity를 표현할 수 있다.

Map 도메인 모델

XML 도메인 모델

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

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Using placeholders

Hibernate/Chapter 3 : 2008.01.13 11:57


특징

  • you can call any native SQL function or keyword your database system supports.
  • The disadvantage of putting native SQL in your mapping metadata is lost database portability.
  • One way to deal with this issue is to use a placeholder in your XML file that is replaced during build when the mapping files are copied to the target directory.

Placeholder

<id name="id" column="CATEGORY_ID" type="long">
<generator class="&idgenerator;"/>
</id>
  • &idgenerator; 값을 Entity placeholder라고 부른다. 이 값을 XML 파일의 상단에 문서 타입 정의의 일부분으로 선언할 수 있다.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
[
<!ENTITY idgenerator "auction.custom.MyOracleGenerator">
]>
  • 맵핑 파일을 읽어들일 때, XML 파서는 placeholder를 위에 선언한 값으로 대체한다.
  • 선언 부분을 별도의 DTD 파일로 한 단계 더 빼낼 수 있고, 원래 자리에는 dtd 파일을 참조하도록 global 옵션을 사용할 수 있다.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
[
<!ENTITY % globals SYSTEM "classpath://persistence/globals.dtd">
%globals;
]>
  • 모든 전역적인 옵션을 DTD 파일로 빼낼 수 있다.
  • 다수의 속성이 여러 클래스에 중복되서 나타나지만, 상속을 사용할 수 없을 때는 XML 덩어리를 별도의 파일로 빼내서 다른 XMl 파일들에 포함 시킬 수도 있다.

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

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Global annotation metadata

Hibernate/Chapter 3 : 2008.01.13 11:56


Package Metadata

  • it's enabled with a file named package-info.java in a particular package directory
애노테이션 글로벌 설정
@org.hibernate.annotations.TypeDefs( {
@org.hibernate.annotations.TypeDef(name = "monetary_amount_usd", typeClass =
MonetaryAmountType.class, parameters = { @Parameter(name = "convertTo", value = "USD") }),
@org.hibernate.annotations.TypeDef(name = "monetary_amount_eur", typeClass =
MonetaryAmountType.class, parameters = { @Parameter(name = "convertTo", value = "EUR") }) })
@org.hibernate.annotations.NamedQueries( { @org.hibernate.annotations.NamedQuery(name =
"findItemsOrderByPrice", query = "select i from Item i order by i.initialPrice)") })
package auction.persistence.types;
  • declares two Hibernate type converters
  • 같은 방법으로 쿼리를 외부화 시키거나 전역 식별자 생성기를 정의할 수 있다.
  • JPA 애노테이션은 package-info.java 파일 안에서 사용할 수 없다.
  • If you need portable global Java Persistence metadata, put it in an orm.xml file.
  • Global annotations (Hibernate and JPA) can also be placed in the source code of a particular class, right after the import section.

모르는 것

  • package-info.java는 '-' 문자 때문에 에러나는데.. 흠;; 어쩌라는 거지?
  • Global 애노테이션을 아무곳에나 놓을 수 있다고? 그럼 package-info.java 파일은 뭐지;; 왜 거기에 넣으라고 한거지?

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

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Global XML mapping metadata

Hibernate/Chapter 3 : 2008.01.13 11:55


<hibernate-mapping>

<hibernate-mapping
schema="AUCTION"
default-lazy="false"
default-access="field"
auto-import="false">

<class ...>
...
</class>

</hibernate-mapping>
  • schema: 스키마 접두어로 사용한다. used by Hibernate for all SQL statements generated for the mapped classes.
  • default-lazy: 이 속성을 false로 하면, you enable default outer-join fetching for some class associations.
  • default-access: 이 속성의 값을 field로 하면, 하이버네이트가 이 파일 내부에 정의한 클래스의 필드에 바로 접근할 수 있다.
  • auto-import: 4장에서 다룸.

Tip

  • This default-lazy="true" switch has an interesting side effect: It switches to Hibernate 2.x default fetching behavior—useful if you migrate to Hibernate 3.x but don't want to update all fetching settings.

모르는 것

  • 스키마 접두어가 뭐지? Whiteship_Member, Whiteship_Group 뭐 이러식으로 테이블 이름이랑 컬럼 이름을 사용한다는 건가?
  • default outer-join fetching은 뭐지?

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

XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
Accessor 메소드에 로직 추가하기  (0) 2008.01.09
top


Handling global metadata

Hibernate/Chapter 3 : 2008.01.13 11:53


전역적인 메타데이타
  • query strings can be externalized to metadata and called by a globally unique name in the application code.
  • a query usually isn't related to a particular class, and sometimes not even to a particular package.
  • Other application-scoped metadata includes user-defined mapping types (converters) and data filter (dynamic view) definitions.
Global XML mapping metadata

Global annotation metadata

Using placeholders

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

Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
Accessor 메소드에 로직 추가하기  (0) 2008.01.09
POJO 관계 구현하기  (0) 2008.01.09
top


XDoclet 사용하기 - 하이버네이트 맵핑

Hibernate/Chapter 3 : 2008.01.11 11:47


XDoclet

  • XDoclet leverages the Javadoc tag format (@attribute) to specify class-, field-, or method-level metadata attributes.
  • XDoclet is implemented as an Ant task that generates Hibernate XML metadata (or something else, depending on the plug-in) as part of the build process.

하이버네이트 XML 생성

XDoclet 사용
/**
* The Category class of the CaveatEmptor auction site domain model.
*
* @hibernate.class table="CATEGORY"
*/
public class Category {
...
/**
* @hibernate.id generator-class="native" column="CATEGORY_ID"
*/
public Long getId() {
return id;
}
...
/**
* @hibernate.property
*/
public String getName() {
return name;
}
...
}

단점

  • 별도의 Ant 태스크 필요해.
  • 배포 할 때마 설정을 좀 바꿔야 할 수도 있어.
  • 개발 환경에서 XDoclet Validation을 수행할 수 없지만, 최근 IDE는 최소한 자동 완성을 제공 해준다.
top


애노테이션 사용하기 - 하이버네이트 맵핑

Hibernate/Chapter 3 : 2008.01.11 11:46


Annotation

  • JDK 5.0에 추가된 기능으로 JDK 1.4이하에서는 XDoclet 이라는 주석에 사용하는 애노테이션을 사용했었다.
  • type-safe and declared interfaces for the definition of annotations.
  • Autocompletion and compile-time checking are no longer an issue.
  • it has better defaults

Annotation 만들기

Entity 애노테이션 정의
package javax.persistence;

@Target(TYPE)
@Retention(RUNTIME)
public @interface Entity {
String name() default "";
}
  • @Target(TYPE)은 메타데이터의 메타데이터로, Entity 애노테이션이 Type위에만 붙일 수 있다는 것을 설정.
  • @Retention(RUNTIME)은 Entity 애노테이션을 하이버네이트가 런타임에도 읽을 수 있도록 보유 정책 설정.
  • 속성과 기본 값 설정할 수 있음.

Annotation 사용하기

Entity 애노테이션 사용
package auction.model;

import javax.persistence.*;

@Entity
@Table(name = "ITEM")
public class Item {
...
}
  • 애노테이션을 사용하면 소스를 수정할 때 같이 리팩터링 할 수 있기 때문에 좋다.

Utilizing vendor extensions

  • fetching and caching settings, are only available as Hibernate-specific annotations.
하이버네이트의 애노테이션 사용하기
package auction.model;

import javax.persistence.*;

@Entity
@Table(name = "ITEM")
@org.hibernate.annotations.BatchSize(size = 10)
@org.hibernate.annotations.DiscriminatorFormula(
"case when ITEM_IS_SPECIAL is not null then A else B end"
)
public class Item {
...
}
  • @BatchSize는 패칭 옵션.
  • @DiscriminatorFormula is especially useful for legacy schemas when class inheritance can't be determined with simple literal values.
  • JPA 표준 애노테이션이 아닌 특정 밴더가 제공하는 애노테이션 앞에는 전체 패키지 이름을 써주는 것이 좋다. 그래야 나중에 밴더가 바뀌더라도 해당 부분만 바꾸기 쉽기 때문이다.
  • 이 애노테이션들은 특정 클래스에 종속적인데, 간혹 다수의 클래스에 적용하고 싶은 메타데이터가 있을 수도 있다.

JPA XML descriptor

  • XML deployment descriptors in certain situations, especially for configuration metadata that changes with each deployment.
  • every annotation in EJB 3.0 and JPA can be replaced with an XML descriptor element
XML descriptor
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
version="1.0">
<persistence-unit-metadata>
<xml-mapping-metadata-complete />
<persistence-unit-defaults>
<schema>MY_SCHEMA</schema>
<catalog>MY_CATALOG</catalog>
<cascade-persist />
</persistence-unit-defaults>
</persistence-unit-metadata>
<package>auction.model</package>
<entity class="Item" access="PROPERTY" metadata-complete="true">
<attributes>
<id name="id">
<generated-value strategy="AUTO" />
</id>
</attributes>
</entity>
</entity-mappings>
  • This XML is automatically picked up by the JPA provider if you place it in a file called orm.xml in your classpath, in the META-INF directory of the persistence unit.
  • 애노테이션 설정을 완전히 무시할 수도 있고, 오버라이딩 하게 할 수도 있다.
  • 하이버네이트 XML 맵핑 파일과 호환되지 않는다.
  • 하이버네이트 XML 맵핑을 사용하면 JPA XML Descriptor보다 더 다양한 맵핑 정보를 표현할 수 있다.
  • 하지만 하이버네이트 XML 맵핑으로 애노테이션을 오버라이딩 할 수는 없다.

모르는 것

  • 애노테이션이 Type-safe 하다는 것이 무슨 뜻일까?
  • @org.hibernate.annotations.BatchSize(size = 10) 무슨 뜻일까?
  • @org.hibernate.annotations.DiscriminatorFormula(
    "case when ITEM_IS_SPECIAL is not null then A else B end"
    ) 무슨 뜻일까?
top


XML 사용하기 - 하이버네이트 맵핑

Hibernate/Chapter 3 : 2008.01.11 11:46


단점

  • Metadata is not, by nature, more flexible or maintainable than plain Java code.
  • Many existing metadata formats weren't designed to be readable and easy to edit by hand. 적절한 기본값을 제공해주지 않아서 필요 이상의 타이핑이 필요하다. 속성없이 엘리먼트만 사용하는 경우도 있다.
  • Good XML editors, especially in IDEs, aren't as common as good Java coding environments. DTD가 제공되지 않아서 자동완성과 검증 기능을 사용하지 못하는 경우가 있다.

하이버네이트의 XML

  • 위의 모든 단점을 고려했다.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

<class name="auction.model.Category" table="CATEGORY">
<id name="id" column="CATEGORY_ID" type="long">
<generator class="native"/>
</id>
<property name="name" column="NAME" type="string"/>
</class>

</hibernate-mapping>
  • 여러 클래스 맵핑 정보를 하나의 파일 안에 모두 두는 것도 가능하지만 클래스 당 매핑 파일 하나를 권장한다.
  • 맵핑 파일은 클래스와 같은 패키지에 놓는것을 권장한다.
top


Accessor 메소드에 로직 추가하기

Hibernate/Chapter 3 : 2008.01.09 16:43


Setter 메소드에 Validation 로직 추가.

  • 하이버네이트가 DB에서 데이터를 가져올 때 이 Setter 메소드를 사용하여 속성을 설정하는데, 그럴 경우에는 validation을 하지 않고 변수에 직접 접근하도록 설정할 수 있다. 어떻게? p122 첫 줄.

Getter 메소드에서 복사체 전달.

  • 하이버네이트는 Dirty Checking을 하기 때문에, Persistent 상태의 객체 속성의 변경을 DB에 반영하기 위해 UPDATE문을 자동으로 실행한다.
  • Getter에서 같은 값의 다른 객체를 반환하더라도 불필요한 Update문을 실행하지 않는다.
다른 객체 반환하는 Getter
public String getFirstname() {
return new String(firstname);
}
  • Hibernate compares the objects by value—not by object identity—to determine whether the property's persistent state needs to be updated.
  • 하지만 Collection일 경우에는 예외이며, 이 경우 같은 객체들을 가진 다른 Collection 객체를 반환하면, 불필요한 UPDATE 문을 실행한다.
다음과 같이 하지 말 것
public void setNames(List namesList) {
names = (String[]) namesList.toArray();
}
public List getNames() {
return Arrays.asList(names);
}

예외 던지기

  • Runtime Exception이 발생하면, 트랜잭션을 롤백하고 Checked Exception이 발생하면, 하이버네이트가 잡아서 Runtime Exception으로 랩핑한다.
참조 : Java Persistence With Hibernate
top


POJO 관계 구현하기

Hibernate/Chapter 3 : 2008.01.09 16:43


Scaffolding code

  • 연관을 맺기 위해 필요한 필드와 메소드.

1:다 관계

  • 다수를 가질 경우, Hibernate requires interfaces for collection-typed attributes
  • 양방향일 경우, 해당 타입의 속성이 필요함.
  • 연결하기: 두 가지 행위가 필요함.
  • Hibernate doesn't manage persistent associations. If you want to manipulate an association, you must write exactly the same code you would write without Hibernate.
  • Convenient Method 도입하기:
1:다 관계
public void addChildCategory(Category childCategory) {
if (childCategory == null)
throw new IllegalArgumentException("Null child category!");
if (childCategory.getParentCategory() != null)
childCategory.getParentCategory().getChildCategories().remove(childCategory);
childCategory.setParentCategory(this);
childCategories.add(childCategory);
}
    • reduces the lines of code
    • enforces the cardinality of the association

다:다 관계

  • both sides are implemented with collection-valued attributes.
  • Convenient Method
다:다 관계
public void addCategory(Category category) {
if (category == null)
throw new IllegalArgumentException("Null category");
category.getItems().add(this);
categories.add(category);
}
  • You can also add logic to your accessor methods.

참조 : Java Persistence With Hibernate
top


하이버네이트와 POJO

Hibernate/Chapter 3 : 2008.01.09 16:41


하이버네이트는 Pesistent 클래스가 Serializable 인터페이스를 구현하도록 강요하지 않지만, 객체가 HttpSession에 저장되어야 하거나 RMI를 사용하여 전송할 것이라면 구현해야한다.

JavaBeans 스펙은 특정 생성자를 필요로 하지 않지만, 하이버네이트(와 JPA)에서 모든 Persistent Class들은 인자가 없는 기본 생성자를 필요로 한다.

생성자는 public이 아니여도 괜찮지만, 만약에 프록시를 사용할 거라면, 최소한 package-visivle(public, protected, default 접근 지시자 사용 가능)해야한다.

프록시를 생성할 때는 클래스가 final이여서도 안되고 final 메소드를 가지고 있어도 안 된다!

Persistent Class 객체들의 상태를 어떻게 하이버네이트가 영속화할지는 필드에 직접 접근하거나 게터, 세터 메소드를 사용하는 방법 중에 선택할 수 있다.

참조 : Java Persistence With Hibernate
top


하이버네이트를 쓰려면 게터 세터가 꼭 필요하다.

Hibernate/study : 2007.12.26 14:58


뻥입니다. 보통 게터 세터를 많이 만들어서 사용하기때문에 이렇게 생각할 수도 있겠습니다. 하지만 미신입니다.

필드에 직접 접근할 수 있습니다.

코딩으로 검증작업은 찬욱군이 해주었습니다.

저는 구글링으로 검증을 해보았습니다.
바로 hibernate-mapping default-access="field" 이런 설정이 검색되었습니다. 하이버네이트 레퍼런스 5.1.2. hibernate-mapping 부분의 설정에 보면 위의 설정이 있습니다.

찬욱군 블로그의 Hibernate 기초 학습[6] - AccessType / fomula 이 글을 보시면 다양한 설정 방법을 참조하실 수 있습니다.
top




: 1 : 2 : 3 : 4 :