2008-08-14 11 views
3

경고 - 나는 NHibernate에있어서 아주 새로운 것이다. 나는이 질문이 단순 해 보인다는 것을 안다 - 나는 간단한 대답이 있다고 확신하지만, 나는이 시간에 내 바퀴를 얼마 동안 돌리고있다. 나는 정말 구조적으로 바꿀 수없는 레거시 DB를 다루고있다. 나는 고객이 수락 한 지불 계획을 열거하는 세부 테이블을 가지고있다. 각 지불 계획에는 계획의 조건, 조건 등을 얻기 위해 참조 테이블로 다시 연결되는 ID가 있습니다. 객체 모델에는 AcceptedPlan 클래스와 Plan 클래스가 있습니다. 원래 NHibernate에서이 관계를 모델링하기 위해 detail 테이블에서 ref 테이블로 다 대 일 관계를 사용했다. Plan 클래스에서 AcceptedPlan 클래스까지 반대 방향으로 일대일 관계를 만들었습니다. 내가 데이터를 읽는 동안 괜찮 았어. 계획의 세부 사항을 읽는 AcceptedPlan 클래스의 속성 인 Plan 개체로 이동할 수 있습니다. 내 문제는 세부 정보 테이블에 새 행을 삽입해야 할 때 발생했습니다. 저의 독서에서 새로운 자식 객체를 생성하는 유일한 방법은 그것을 부모 객체에 추가 한 다음 세션을 저장하는 것입니다. 하지만 새로운 세부 레코드를 만들 때마다 새로운 부모 Plan 개체를 만들어야하는 것은 아닙니다. 이것은 불필요한 오버 헤드처럼 보입니다. 내가 잘못된 방향으로 갈 것인지 아는 사람 있습니까?레거시 데이터베이스를 다룰 때 NHibernate의 다 대일 관계를 모델링하는 가장 좋은 방법은 무엇입니까?

답변

3

나는 부모 객체를 포함하는 자식 객체를 가지고 있지 않으므로 그렇게 할 때 매우 복잡하고 매우 재귀적일 수 있습니다. 나는 당신이 그런 종류의 일을하기 전에 어떻게 도메인 모델을 사용하려고하는지 살펴볼 것입니다. 테이블에 ID 참조가 있으면 쉽게 매핑 할 수 있습니다.

다음은 올바른 방향으로 사용자를 뉘앙스시킬 수있는 매핑 예입니다. 테이블 이름 등을 adlib해야했지만 도움이 될 수 있습니다. 나는 또한 StatusId를 열거 형에 매핑하는 것이 좋습니다.

가방이 세부 정보 테이블을 효과적으로 컬렉션으로 매핑하는 방식에주의하십시오.

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2"> 
    <class lazy="false" name="Namespace.Customer, Namespace" table="Customer"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="CustomerAccountId" length="4" sql-type="int" not-null="true" unique="true" index="CustomerPK"/> 
      <generator class="native" /> 
     </id> 

     <bag name="AcceptedOffers" inverse="false" lazy="false" cascade="all-delete-orphan" table="details"> 
      <key column="CustomerAccountId" foreign-key="AcceptedOfferFK"/> 
      <many-to-many 
      class="Namespace.AcceptedOffer, Namespace" 
      column="AcceptedOfferFK" 
      foreign-key="AcceptedOfferID" 
      lazy="false" 
      /> 
     </bag> 

    </class> 
</hibernate-mapping> 


<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2"> 
    <class lazy="false" name="Namespace.AcceptedOffer, Namespace" table="AcceptedOffer"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="AcceptedOfferId" length="4" sql-type="int" not-null="true" unique="true" index="AcceptedOfferPK"/> 
      <generator class="native" /> 
     </id> 

     <many-to-one 
      name="Plan" 
      class="Namespace.Plan, Namespace" 
      lazy="false" 
      cascade="save-update" 
     > 
     <column name="PlanFK" length="4" sql-type="int" not-null="false"/> 
     </many-to-one> 

     <property name="StatusId" type="Int32"> 
      <column name="StatusId" length="4" sql-type="int" not-null="true"/> 
     </property> 

    </class> 
</hibernate-mapping> 
0

나는 다음과 같이이 모델이 걸릴 것 접근 :

고객 개체가 ICollection은 고객이 수락하는 계획을 나타냅니다 <PaymentPlan> PaymentPlans가 포함되어 있습니다.

고객에 대한 PaymentPlan은 details 테이블을 사용하여 어떤 PaymentPlans에 매핑 된 고객 ID를 설정하는 가방을 사용하여 매핑됩니다. cascade all-delete-orphan을 사용하여 고객이 삭제 된 경우 세부 사항의 항목과 고객이 소유 한 PaymentPlans가 모두 삭제됩니다.

PaymentPlan 개체는 지불 계획의 조건을 나타내는 PlanTerms 개체를 포함합니다.

PlanTerms는 관련된 PlanTerms 개체에 대한 참조를 PaymentPlan에 삽입하는 다 대일 매핑 계단식 저장 업데이트를 사용하여 PaymentPlan에 매핑됩니다.

이 모델을 사용하면 PlanTerms를 독립적으로 생성 한 다음 고객에게 새 PaymentPlan을 추가 할 때 관련 PlanTerms 객체를 전달하는 새 PaymentPlan 객체를 만든 다음 관련 고객의 컬렉션에 추가 할 수 있습니다 . 마지막으로 고객을 저장하고 nhibernate가 저장 조작을 계단식으로 처리하도록합니다.

고객 (고객 테이블)이 PaymentPlans 인스턴스 (세부 테이블)를 소유하는 고객 개체, PaymentPlan 개체 및 PlanTerms 개체는 특정 PlanTerm (계획 테이블)을 모두 준수해야합니다.

필자는 필 요한 경우 매핑 구문에 대해 좀 더 구체적인 예를 들었지만 고유 한 모델을 사용하여 작업하는 것이 가장 좋으며 특정 예제를 제공하기에 충분한 정보가 데이터베이스 테이블에 없습니다.

0

내 NHibernate 환경이 제한되어 있기 때문에 가능할지 모르겠지만 세부 정보 테이블에 직접 매핑 될 때 세부 정보의 속성 만있는 BaseDetail 클래스를 만들 수 있습니다.

그런 다음 추가 상위 계획 개체가있는 BaseDetail 클래스에서 상속되는 두 번째 클래스를 만듭니다. 따라서 세부 행을 만들고 PlanId를 할당 할 때 BaseDetail 클래스를 만들 수 있습니다.하지만 필요한 경우 상속 된 Detail 클래스를 사용할 수있는 상위 계획 개체와 함께 전체 세부 정보 레코드를 채 웁니다.

나는 그것이 많은 의미를 가지는지 모르지만 나에게 알려 주면 더 명확히 할 것입니다.

0

여기에있는 문제는 AcceptedOffer 개체에 Plan 개체가 들어 있고 Plan 개체에 AcceptedOffer 개체가 들어있는 AcceptedOffers 컬렉션이있는 것으로 보입니다. 고객에게도 마찬가지입니다. 객체가 서로의 자식이라는 사실 때문에 문제가 발생합니다.

마찬가지로 AcceptedOffer 컴플렉스는 두 가지 책임이 있습니다. 이는 제안서가 계획에 포함되어 있음을 나타내며 고객이 수락 함을 나타냅니다. 그것은 Single Responsibility Principle에 위배됩니다.

계획에 따른 제안과 고객이 승인 한 제안을 구별해야 할 수도 있습니다. 그래서 다음과 같이해야 할 일이 있습니다 :

  1. 상태가없는 별도의 Offer 객체를 만듭니다. 예를 들어, 고객이없고 상태가 없습니다. OfferId 만 있습니다. 그리고 그것의 속성으로 속한 계획.
  2. Plan 개체가 Offers 컬렉션을 갖도록 수정합니다 (제안 내용을 받아 들일 필요가 없음).
  3. 마지막으로 Offer, Customer 및 Status가 포함되도록 AcceptedOffer 개체를 수정합니다. 고객은 동일하게 유지됩니다.

나는 이것이 당신의 NHibernate 매핑과 객체 절약 문제를 충분히 해결할 수 없을 것이라고 생각한다. :)

0

(또는하지 않을 수) NHibernate에 도움이 될 수 있습니다 팁 :보기 테이블이었다 것처럼 당신이보기에 당신의 객체를 매핑 할 수 있습니다. 뷰 이름을 테이블 이름으로 지정하십시오. 모든 NOT NULL 필드가 뷰에 포함되어 있고 매핑이 정상적으로 작동하는 한.

1

필자가 작성한 동안 데이터베이스 다이어그램을 보지 못했습니다.

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2"> 
    <class lazy="false" name="Namespace.Customer, Namespace" table="Customer"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="customer_id" length="4" sql-type="int" not-null="true" unique="true" index="CustomerPK"/> 
      <generator class="native" /> 
     </id> 

     <bag name="AcceptedOffers" inverse="false" lazy="false" cascade="all-delete-orphan"> 
      <key column="accepted_offer_id"/> 
      <one-to-many class="Namespace.AcceptedOffer, Namespace"/> 
     </bag> 

    </class> 
</hibernate-mapping> 


<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2"> 
    <class lazy="false" name="Namespace.AcceptedOffer, Namespace" table="Accepted_Offer"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="accepted_offer_id" length="4" sql-type="int" not-null="true" unique="true" /> 
      <generator class="native" /> 
     </id> 

     <many-to-one name="Plan" class="Namespace.Plan, Namespace" lazy="false" cascade="save-update"> 
      <column name="plan_id" length="4" sql-type="int" not-null="false"/> 
     </many-to-one> 

    </class> 
</hibernate-mapping> 

트릭을 (난 단지 다른 속성을 추가해야합니다, 컬렉션에 대한 예를 매핑을 완료했습니다) 할 아마도합니다.