NHibernate-컬렉션 매핑
이 장에서는 컬렉션을 표현하는 방법을 다룰 것입니다. NHibernate 내에서 사용할 수있는 다양한 유형의 컬렉션이 있습니다.
- Lists
- Sets
- Bags
이제 .NET 관점에서 우리는 일반적으로 목록 또는 매우 간단한 데이터 구조, 목록, 사전과 같은 것을 처리합니다. .NET에는 다양한 컬렉션 유형이 없습니다. 그렇다면 NHibernate는 왜 이러한 모든 유형을 필요로합니까? 실제로 데이터베이스로 돌아옵니다.
명부
목록은 반드시 고유하지 않은 순서가 지정된 요소 모음입니다.
이것을 사용하여 매핑 할 수 있습니다. IList <T>.
따라서 일반적으로 주소 목록이 있고 응용 프로그램의 관점에서 요소가 고유하다는 것을 알고 있지만 목록의 어떤 것도 해당 목록에 중복 요소를 삽입하는 것을 방해하지 않습니다.
세트
집합은 고유 한 요소의 순서가 지정되지 않은 컬렉션입니다. 두 개의 중복 요소를 세트에 삽입하려고하면 예외가 발생합니다.
NHibernate에는 특별한 것이 없습니다.
일반적인 집합 구현을 갖는 편리한 방법입니다. .NET 4를 사용하는 경우 새로운HashSet <T> 그러나 대부분의 NHibernate 애플리케이션에서 우리는 이것이 ISet임을 나타냅니다.
순서가 지정되지 않은 것입니다. 데이터베이스 또는 주문 목록에서 주소 목록을 가져 오면 특정 Order by 절을 입력하지 않는 한 어떤 순서로 들어오는 지 알 수 없습니다.
따라서 일반적으로 데이터베이스에서 다시 가져 오는 데이터는 집합입니다.
순서가 지정되지 않은 고유 한 요소 모음입니다.
가방
데이터베이스 세계에서 볼 수있는 또 다른 일반적인 컬렉션은 가방으로, 중복 요소를 가질 수 있다는 점을 제외하면 집합과 같습니다.
.NET 세계에서 우리는 이것을 IList로 표현합니다.
세트는 아마도 가장 일반적이지만 응용 프로그램에 따라 목록과 가방도 표시됩니다. 아래를 살펴 보겠습니다.customer.hbm.xml 세트 순서가 정의 된 마지막 장의 파일.
<?xml version = "1.0" encoding = "utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
namespace = "NHibernateDemo">
<class name = "Customer">
<id name = "Id">
<generator class = "guid.comb"/>
</id>
<property name = "FirstName"/>
<property name = "LastName"/>
<property name = "AverageRating"/>
<property name = "Points"/>
<property name = "HasGoldStatus"/>
<property name = "MemberSince" type = "UtcDateTime"/>
<property name = "CreditRating" type = "CustomerCreditRatingType"/>
<component name = "Address">
<property name = "Street"/>
<property name = "City"/>
<property name = "Province"/>
<property name = "Country"/>
</component>
<set name = "Orders" table = "`Order`">
<key column = "CustomerId"/>
<one-to-many class = "Order"/>
</set>
</class>
</hibernate-mapping>
보시다시피 주문 컬렉션을 세트로 매핑했습니다. 집합은 순서가 지정되지 않은 고유 한 요소의 모음입니다.
이제 Customer 클래스를 보면 다음 프로그램과 같이 Orders 속성이 ISet으로 정의되어 있음을 알 수 있습니다.
public virtual ISet<Order> Orders { get; set; }
이제이 응용 프로그램이 실행되면 다음 출력이 표시됩니다.
New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
CreditRating: Good
AverageRating: 42.42424242
Orders:
Order Id: 00000000-0000-0000-0000-000000000000
Order Id: 00000000-0000-0000-0000-000000000000
Reloaded:
John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7
The orders were ordered by:
John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7
John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7
Press <ENTER> to exit...
컬렉션의 항목이 고유 할 필요가없는 경우이 컬렉션에서 동일한 기본 키가 여러 번 발생하는 여러 주문이있을 수 있다면 다음 프로그램과 같이 가방으로 매핑하는 것이 더 좋습니다.
<bag name = "Orders" table = "`Order`">
<key column = "CustomerId"/>
<one-to-many class = "Order"/>
</bag>
이제이 애플리케이션을 실행하면 예외가 발생합니다. 고객 클래스를 살펴보면 주문이 C # 코드에서 ISet으로 표시되어 있음을 알 수 있습니다.
그래서 우리는 또한 이것을 IList로 변경해야 할 것입니다. 그리고 여기서 우리는 생성자의 HashSet에서 List로 변경해야합니다.
public class Customer {
public Customer() {
MemberSince = DateTime.UtcNow;
Orders = new List<Order>();
}
public virtual Guid Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual double AverageRating { get; set; }
public virtual int Points { get; set; }
public virtual bool HasGoldStatus { get; set; }
public virtual DateTime MemberSince { get; set; }
public virtual CustomerCreditRating CreditRating { get; set; }
public virtual Location Address { get; set; }
public virtual IList<Order> Orders { get; set; }
public virtual void AddOrder(Order order) { Orders.Add(order); order.Customer = this; }
public override string ToString() {
var result = new StringBuilder();
result.AppendFormat("{1} {2} ({0})\r\n\tPoints: {3}\r\n\tHasGoldStatus:
{4}\r\n\tMemberSince: {5} ({7})\r\n\tCreditRating: {6}\r\n\tAverageRating:
{8}\r\n", Id, FirstName, LastName, Points, HasGoldStatus, MemberSince,
CreditRating, MemberSince.Kind, AverageRating); result.AppendLine("\tOrders:");
foreach(var order in Orders) {
result.AppendLine("\t\t" + order);
}
return result.ToString();
}
}
응용 프로그램을 실행하면 동일한 동작이 나타납니다. 그러나 이제 동일한 컬렉션에서 여러 번 주문이 발생할 수 있습니다.
John Doe (00000000-0000-0000-0000-000000000000)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
CreditRating: Good
AverageRating: 42.42424242
Orders:
Order Id: 00000000-0000-0000-0000-000000000000
Order Id: 00000000-0000-0000-0000-000000000000
Reloaded:
John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287
The orders were ordered by:
John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287
John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287
Press <ENTER> to exit...