본문 바로가기
연재/NHibernate

[챕터5] 도메인 모델간의 연관(association)관계 설정 - 1 대 N

by 그저그런보통사람 2011. 8. 20.


데이터 모델링에서 관계(Relationship)는  빠질 수 없는 내용입니다.
현대에 가장 많이 사용되는 데이터베이스가 RDBMS (Relational Database Management System)로 불리우는 것처럼 업무의 흐름과 구조를 명확하게 하고, 정보의 가치에 대한 무결성을 확보하는데 있어서 관계는 언제나 선택이 아닌 필수입니다.

이러한 데이터 모델은 비즈니스 요구사항으로 만들어집니다. 이를 생산적으로 구현하기 위해 다양한 모델링 도구가 사용되는데, 이러한 도구는 보통 DB 플랫폼과 함께하고 있습니다. 과거부터 사용되어 왔던 방법이며, 우리도 익숙한 설계 스타일이기도 합니다.

하이버네이트 관점에서 DB는 비즈니스가 존재해서는 안되는 오로지 데이터만 저장하는 저장소로 보고 있습니다.
각 도메인 모델에 대한 관계는 특정 DB 플랫폼(벤더)에 종속적이지 않으며, 비즈니스 개발 이전에 선행되는 데이터 모델링은 그래서 특정 DB에 맞추지 않고 설계합니다. 기존 방식으로 진행한다면 논리 설계 후 물리 설계 시점에 특정 벤더에 종속성을 갖게 되버립니다.

하지만, 하이버네이트는 .NET API 에서 제공하는 타입으로 자료형을 정의하고, 실제 포팅에 들어가면 각각의 벤더에 맞게 구체화되어 생성됩니다. 이전 글에서 언급했던 "벤더의 종속성으로 자유로운 뛰어난 이식성"에 대한 내용입니다.

관계 이야기를 하다가 뜬금없이 종속성과 이식성까지 넘어왔는데, OOP 에서도 DB모델링과 동일하게 관계를 풀어낼 수 있습니다. 이를 보통 연관(association)관계 설정이라고 하는데, 하이버네이트에서 이러한 OOP 연관관계를 통해 좀 더 다양한 기능을 제공하여 개발에 편의성을 제공합니다.

일단 시작해 볼까요?!
1 : N 을 구현해보도록 하겠습니다.

"[챕터2] 프로젝트 시작하기"에서 작성했던 비즈니스 논리 설계 모델에서 1:N 관계는 회원과 게시판, 게시판과 댓글, 그리고 회원과 댓글이 있었습니다.
이 중에서 회원과 게시판과의 관계를 구현해보도록 하겠습니다.

우선 게시판 도메인 모델 클래스(BoardPost.cs)를 추가해서 아래와 같이 작성합니다.


그리고 매핑 메타데이터 XML (BoardPost.hbm.xml) 을 작성합니다. (각각 어디에 위치하는지 설명이 필요하진 않겠죠 ^^)

(* 다시 한번 언급하지만 xml 매핑 파일은 속성이 "포함 리소스(Embedded Resource)"여야 하며 파일명과 확장자 사이에 .hbm이 포함되어야 합니다.)

이전 챕터에서 작성한 회원 도메인과 방금 작성한 게시물(게시판)에 대한 연관관계를 설정해야 합니다.
회원과 게시물은 1:N 관계임으로 회원은 게시물에 대한 컬렉션(IList<BoardPost>)을 가지면 될 것이고, 게시물은 회원에 대한 단일 참조(Member)를 가지면 될 것입니다. 

우선 도메인 클래스를 작성합니다. 


다시 설명드리자면,

회원과 게시물은 1 : N 관계이기 때문에 회원은 여러(N) 게시물을 작성할 수 있습니다.
그래서 Member 클래스의 멤버로 BoardPost 클래스의 컬렉션을 가질 수 있습니다.

반대로 게시물은 오로지 한 명의 회원에게서만 작성되기 때문에 BoardPost 클래스는 컬렉션이 아닌 단일 클래스를 멤버로 Member 클래스를 가지게 됩니다. 


이제 DB와의 매핑을 위해 xml 메타데이터를 작성합니다.

* 회원


* 게시물


회원에 추가된 <bag> 은 "가방"의 의미처럼 "담아 다닌다는" 뜻으로 이해하면 되겠습니다. 오히려 이런 설명 자체가 더욱 혼란을 가중시키기도 하는데, 그래서 그냥 컬렉션으로 이해해도 무방합니다.
컬렉션을 다루는 요소는 <bag> 외에도 <set>, <list>, <map> 등등이 있습니다.

컬렉션을 다루는 <bag> 의 속성 중 cascade 와 inverse 는 매우 중요하며, 컬렉션을 다루면서 대부분 사용하게 될 것입니다.
먼저 cascade 속성을 설명하기 전에 테이블간의 "부모"와 "자식"간의 관계에 대해서 이야기 해보겠습니다. 보통 부모는 자식을 낳아 기르게 됩니다. 주체는 부모가 되는 것이고 자식은 "부모의 의해서" 라는 관점에서 바라볼 수 있게됩니다.
여기서 cascade의 목적이 들어나는데, 부모 엔터티가 등록될 때 자식 엔터티도 같이 관리할 수 있도록 하는 기능입니다.

다음은 새로운 부모와 자식을 만들어 저장하는 코드입니다.

cascade 옵션을 통해 부모 엔터티를 영속화(영속화? 잠깐 아래의 더보기로)하면서 자식 엔터티까지 영속화해 줄 수 있습니다.
만약 연속적인(cascade) 기능이 없다면 관계가 있는 부모와 자식을 영속화할 때 각각 처리문이 존재해야 할 것입니다.

save(member);
save(post);

이런 식으로 말이죠. cascade 옵션으로 save(member); 하나로 자식 엔터티까지 영속화가 실현됩니다.

영속화란?


cascade 값이 "save-update, delete"로 되어 있습니다. cascade 값은 all, save-update, delete, all-delete-orphan
이 있으며 두 가지 이상의 특성을 적용하고자 할때에는 ",(콤마)" 로 구분하면 됩니다. 위에서는 save-update와 delete를 지정했습니다. 이는 연속적인 작업을 진행할 때 저장/수정삭제에 대해서 처리하겠다는 뜻입니다.



@@@@ 현재 개인적인 이유 (업무가 바쁘고 다른 일에 치우친 관계로)로 인해 상당히 업데이트가 늦어지고 있습니다. 이 부분은 정말정말 죄송하게 생각합니다. 해서 그동안 작성했던 내용이라도 일단 올리겠습니다. 차후에 마저 작성해서 올리겠습니다. 업데이트는 계속 진행할 것입니다. 2011-12-27.  헉! 그러고 보니 8월에 작성한게 벌써 3개월이 지났네요 ;;;; @@@@