레이블이 hbm인 게시물을 표시합니다. 모든 게시물 표시
레이블이 hbm인 게시물을 표시합니다. 모든 게시물 표시

2012년 12월 8일 토요일

Hibernate Mapping 방식 비교


Hibernate Mapping 방식은
  1. 전통적인 HBM (Hibernate Mapping) XML 파일 방식
  2. JPA 표준으로 사용되는 Annotation 방식
이 있습니다.

처음 Hibernate를 접하시는 분들은 어떤 것을 배워야 쉽고 빠르게 배울수 있을까 고민이 될 것입니다.
이 글은 그런 분들에게 도움이 되고자 쓰는 글이므로, 이미 익숙한 방법이 있는 경험자는 자신에게 익숙한 방식을 사용하는 것을 첫번째로 고려하시기 바랍니다.

자 그럼 두 가지 방식의 얘를 먼저 보고 얘기해 보도록 하지요.


우선 기존 HBM 방식인 XML로 Customer 정보와 Address 정보를 join 을 이용하여 1:1 테이블을 만드는 방식에 대한 매핑을 구현한 예를 보시죠.
보시다시피 초보자가 해석하거나 작성하는 것은 좀 버거워 보이죠? 다만 좋은 IDE를 사용하신다면, DTD나 XSD를 기준으로 HBM의 골격을 해석하여, 입력 정보를 추천해 줄 것이므로, 그리 걱정하지 않으셔도 됩니다. 하지만 각 Xml Element의 의미를 잘 이해해하는 것은 너무나 당연한 것이겠지요^^

HBM 내부 코드를 간략히 설명하자면, Join_Customer라는 Entity 에 id, name, email 등의 단순 속성을 가지고, Address 라는 Value Object 를 가지는데, Address 정보는 다른 테이블에 저장하여, Customer - Address 가 1:1 관계를 가지게 되도록 합니다.


 

  
   
  

  
  
  

  

  
   
   
    
    
    
           
  
 



다음은 Annotation으로 Entity를 매핑하는 방식으로 살펴보겠습니다.
@Entity 가 엔티티를 표현하는 것이고, @Table은 저장 테이블의 명칭 등을 지정할 수 있습니다.
@SecondaryTable 이 Address가 저장될 join table을 지정하구요. 당연히 두 테이블이 1:1 매핑이 되려면 FK가 있어야 하니 CUSTOMER_ID가 FK가 되도록 지정합니다.

각 속성들이 매핑 정보는 각 속성의 annotation 으로 지정하면 됩니다.
HBM 방식과 크게 차이는 나지 않지요? JPA 표준을 만들때 Hibernate 주요 개발자들이 많이 참여하여 주도 했다고 하네요. 그래서 이질감이 덜한 거 같더군요

package org.jpa.example.domain.model.join;

import com.google.common.base.Objects;
import kr.kth.commons.tools.HashTool;
import kr.kth.data.jpa.domain.JpaEntityBase;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;

import javax.persistence.*;
import java.util.Date;

/**
 * org.jpa.example.domain.model.join.JpaJoinCustomer
 * User: sunghyouk.bae@gmail.com
 * Date: 12. 12. 4.
 */
@Entity
@Table(name = "JPA_JOIN_CUSTOMER")
@SecondaryTable(name = "JPA_JOIN_CUSTOMER_ADDR", pkJoinColumns = @PrimaryKeyJoinColumn(name = "CUSTOMER_ID"))
@Getter
@Setter
public class JpaJoinCustomer extends JpaEntityBase {

 private static final long serialVersionUID = 6609847114968580068L;

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "CUSTOMER_ID")
 private String id;

 @Column(name = "CUSTOMER_NAME")
 private String name;

 @Column(name = "CUSTOMER_EMAIL")
 private String email;


 @Embedded
 @AttributeOverrides(
  {
   @AttributeOverride(name = "street",
                      column = @Column(name = "STREET", table = "JPA_JOIN_CUSTOMER_ADDR")),
   @AttributeOverride(name = "zipcode",
                      column = @Column(name = "ZIPCODE", table = "JPA_JOIN_CUSTOMER_ADDR")),
   @AttributeOverride(name = "city",
                      column = @Column(name = "CITY", table = "JPA_JOIN_CUSTOMER_ADDR")),
  }
 )
 private JpaJoinAddress joinAddress = new JpaJoinAddress();

 @Temporal(TemporalType.TIMESTAMP)
 @Generated(GenerationTime.INSERT)
 @Column(name = "CREATED_TIME", insertable = false, updatable = false)
 //@Setter(AccessLevel.PROTECTED)
 private Date created;

 @Temporal(TemporalType.TIMESTAMP)
 @Generated(GenerationTime.ALWAYS)
 @Column(name = "UPDATED_TIME", insertable = false, updatable = false)
 //@Setter(AccessLevel.PROTECTED)
 private Date lastUpdated;

 @Override
 public int hashCode() {
  if (isPersisted())
   return HashTool.compute(id);

  return HashTool.compute(name);
 }

 @Override
 protected Objects.ToStringHelper buildStringHelper() {
  return super.buildStringHelper()
              .add("id", id)
              .add("name", name)
              .add("email", email);
 }
}

흠 그럼 본격적으로 두 가지 방식에 대한 차이점을 살펴볼까요?

HBM 방식을 보면서, 무었을 느꼈습니까? HBM 방식은 기존 엔티티 클래스에 어떠한 매핑 정보도 없겠지요? HBM 파일에 모두 정의했으니까요? 즉 엔티티와 매핑 정보를 분리한 것이죠? annotation은 두 정보가 결합된 것이구요. 사실 이 차이밖에 더 없습니다^^

그럼 장단점은 무엇일까요?

분리 시 장점은 당연히 독립적이므로 코드를 따로 쓸 수 있고, 매핑에 대한 변화 시에 기존 코드는 고치지 않고, 매핑 정보만 변경하여 적용 시킬 수 있습니다. 즉 유연성 측면에서 좀 더 좋은 방법이다!!! 라고 할 수 있습니다.

또 한가지는 코드 공개를 단계적으로 하고 싶을 때가 있습니다. HBM만 공개하던가, Java Class 만 공개하던가 하게 되면, 전체 그림을 파악 못하게 할 수 있습니다.

이 것은 장점도 될 수 있고, 단점도 될 수 있겠죠? 유지보수 담당자 입장에서는 한번에 파악하는 것이 좋을 수 있으니, SI 나 서비스 개발 분야라면 한 번에 파악하는 게 좋을 수 있고, 솔루션을 개발하거나  보안이 중요한 분야에서는 분리하는 것이 좋을 수 있습니다.

학습측면을 고려한다면... Hibernate 의 기본 매핑 방식은 HBM 이므로, 많은 자료가 있을 것입니다. 쉽게 참조할 자료가 많습니다. (버전별로 매핑 기능이 추가가 된 것이 많기는 하지만 ) 그래서 좀 더 유리하다고 할 수 있겠지요.

다만 요즘은 annotation 방식으로 개발하는 개발자도 꽤 돼므로, StackOverflow 같은 데 보면 annotation 방식으로 질/답하는 예가 더 많은 것 같더군요.

개인적으로는 HBM 방식은 이미 잘 알고 있습니다. 그래서 요즘은 annotation 방식으로 개발 하려고 합니다. 이유는 첫째, 안써본 방식을 더 알고 싶다는 욕심이 있고, 둘째, 저의 직장이 서비스 개발이 주요 업무이다 보니, 보안성이나 유연성보다 유지보수성이 우선 시 된다는 점입니다.

저와 다른 선호도를 가지셨거나, 솔루션 업체에 계시다면 HBM 방식을 추천합니다.

다음에는 Hibernate 공부에 가장 걸림돌이 되는 테스트 환경 구성에 대해 글을 써 볼까 합니다.
그 다음부터는 Hibernate 의 여러가지 매핑 방식에 대해 몇 단계로 나누어 글을 써 보겠습니다.