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 의 여러가지 매핑 방식에 대해 몇 단계로 나누어 글을 써 보겠습니다.

댓글 없음: