2011년 10월 14일 금요일

NHibernate Code Mapping 비교 – Join

NHibernate 사용 시 매핑은 필수이고, 그 동안 HBM 만을 사용했었습니다.
이유는 없고, 많은 참고 자료와 익숙해져 있어서였습니다만, 회사 팀원들이 이제 NHibernate 자체에 많이 익숙해져서, 새로운 시도를 해 봤습니다.
물론 그 시도라는 것은 FluentNHibernate 를 이용한 Code Mapping 입니다.
FluentNHibernate 소개를 보시면 알겠지만, 가장 큰 특징은 Code로 Mapping 을 정의하는 것이고, 부가적으로 자동으로 Mapping 테스트도 할 수 있다는 장점이 있습니다.
그럼 오늘은 HBM, FluentNHibernate, NH 3.2 Build-In Code Mapping 을 간단한 예를 가지고 비교해 보겠습니다.
아주 간단한 예 중에 하나의 entity를 두 개의 Table 의 1:1 매핑으로 표현하는 방식인 <join /> 이라는 방식에 대한 구현을 보겠습니다.
엔티티 클래스는 다음과 같습니다.
 
using System;

namespace RCL.Data.NH.DomainModel.Mappings.JoinTable
{
 public class JoinMaster : DataEntityBase<Int32>
 {
  public virtual string Name { get; set; }
 
  public virtual string NickName { get; set; }
 
  public virtual string Description { get; set; }
 }
}



보시다시피, 3개의 Property가 있습니다. Name 속성은 “JoinMaster” 테이블에 저장되고, NickName과 Description은 “JoinDetail” 테이블에 저장되고, 1:1 매핑이 되게 합니다.

기본 HBM 방식으로 Mapping 을 정의한다면 다음과 같습니다.

결과를 보시면, 뭐 별거 아니잖아 하실 것입니다…




  
   
  

  

  
   
   
   
   
  
     
 

NHibernate 에 대해 초급자 수준이라도 쉽게 이해가 되실 것입니다. 

그럼 이런 매핑을 FluentNHibernate 를 이용하여 매핑한다면 다음과 같게 정의할 수 있습니다.
using FluentNHibernate.Mapping;

namespace RCL.Data.NH.DomainModel.Fluent.Mappings
{
 public class FJoinMasterMap : ClassMap
 {
  public FJoinMasterMap()
  {
   Table("FJoinMaster");
   LazyLoad();
   DynamicInsert();
   DynamicUpdate();

   Id(x => x.Id).Column("MasterId").GeneratedBy.Native();

   Map(x => x.Name);

   Join("FJoinDetail", m =>
                       {
                        m.Map(x => x.NickName);
                        m.Map(x => x.Description);
                       });
  }
 }
}

FluentNHibernate 를 직접 사용해보면, Lambda Expression을 사용하게 되어, 손 쉽게 Proeprty 를 매핑할 수 있도록 Intellisense에 나타나게 되어 매핑이 손쉽게 됩니다.
(이 매핑에서 “F” 라는 접두사를 둔 것은 HBM 방식의 매핑과 같은 DB에 생성하기 위해 구분을 위해 넣었습니다.)

다음은 NH-3.2에 새로 제공되는 Built-In Code Mapping 방식을 살펴보겠습니다.


using NHibernate.Mapping.ByCode;
using NHibernate.Mapping.ByCode.Conformist;

namespace RCL.Data.NH.DomainModel.Loquacious
{
 public class CJoinEntityMap : ClassMapping
 {
  public CJoinEntityMap()
  {
   Table("CJoinEntity");
   Lazy(true);
   DynamicInsert(true);
   DynamicUpdate(true);

   Id(x => x.Id, c => c.Generator(Generators.Native));

   Property(x => x.Name);

   Join("CJoinEntityDetail",
        jm =>
        {
         jm.Property(x => x.NickName);
         jm.Property(x => x.Description, c => c.Length(9999));
        });
  }
 }
}


NH-3.2 Code Mapping 방식은 Lambda Expression을 사용했지만, Fluent 방식 (Method Chain) 을 사용하지 않아, 코드가 좀 길어진 느낌입니다. 다만 메소드 명칭이 HBM의 XML Element 요소명과 같아, 쉽게 기억할 수 있는 점이 장점입니다.

HBM 방식의 장점은 기존 매핑에 대한 많은 방식이 HBM으로 되어 있어, 공부하기에는 좋습니다. 즉 기초를 닦기 위해서는 HBM을 꼭 학습해야 합니다.

FluentNHibernate 방식은 실행 시 HBM을 생성하여, NHibernate가 Deserialize를 수행하는 방식이라, 첫 실행 시에 성능 문제가 제기될 수 있지만, 웬만한 시스템에서는 별 의미 없는 단점이라 할 수 있습니다. 코드 매핑의 장점으로는 “Magic String” 을 사용하지 않아, 유지보수나 Refactoring 시에 상당히 유용하다고 볼 수 있습니다.

NH-3.2 Code Mapping 방식은 Code Mapping의 장점과 내부 API 라는 장점으로 XML Deserialize 단계를 생략하게 됩니다. 결국 NHibernate 초기화 비용이 가장 적게 든다고 볼 수 있습니다. 다만 매핑 방식이 Fluent 방식이 아니라, 코드가 길어지고, 가독성이 떨어진다는 점이 단점이라 볼 수 있습니다. 또한 첫 번째 버전이라 그런지, MySQL 이나 PostgreSQL 에서는 매핑이 제대로 안 되는 경우가 있습니다. (앞으로 나올 NH 3.2.1 도 마찮가지로 안됩니다)

여러분은 어떤 방식을 쓰시겠습니까?
저희 회사 내부에서는 압도적으로 FluentNHibernate가 인기가 있더군요

댓글 4개:

Unknown :

저도 Fluent Interface(or Method Chain) 방식을 선호하는 편이지만 FluentNHibernate의 경우에는 런타임에 내부적으로 hbm 리소스가 별도로 생성되는 과정을 똑같이 거치는 것으로 알고 있습니다. NH3.2에 추가된 방식은 그 과정을 거치지 않는 것으로 알고 있습니다. 따라서 성능면에서는 NH3.2 쪽이 좀 더 유리하지 않은가 싶은데요. 실제 업무에서 사용하시는 입장에서 체감하시는 바가 있으신지 궁금합니다.

Unknown :

아참 그리고 좋은 정보 감사합니다~

Unknown :

본문에도 있듯이 확실히 NH-3.2가 두 단계를 생략하므로, 초기화 비용이 절약됩니다. 다만 실제 웹 Application 경우는 초기화가 그리 큰 비중을 차지하지 않기에 별 무리가 없습니다.

저 개인적으로는 NH-3.2를 쓰겠지만, 팀 차원이나, 교육을 위해서는 FNH를 쓰는 걸 추천드립니다.

Unknown :

답변 감사합니다 ^^
말씀 하신 대로 확실히 처음에는 hbm으로 배우는게 좋다고 생각합니다. 저역시 2년 전 쯤 NHibernate에 관한 제대로 된 책 하나 없는 상황에서 자바의 Hibernate 관련 서적을 구해 보면서 hbm 작성하는 법을 익혔었는데요. DB의 테이블이 많은 경우엔 hbm을 일일이 작성하는 일이 만만치 않아서 VisualNhibernate 같은 도구를 써볼까 하는 생각도 했었습니다. 지금은 Entity Framework를 쓰다 보니 그 자동화 된 도구의 매력이란게 여간 매력적인게 아니네요. ㅎㅎ NH3.2가 릴리즈되면서 다시 살펴보고 있습니다. 디밥님 정도의 노하우라면 NHibernate 관련해서 책을 한권 써 주시면 닷넷 플젝에 ORM의 저변을 확대하는데 큰 도움이 될 것 같은 생각이 듭니다.