1

MyItem というエンティティがあるとします。SomeCollection や SomeOtherCollection など、多くの「親」に含めることができます。多くの親に含めることができ、MyItem に親について知られたくないので、親を参照する MyItem にプロパティを持たないようにしたいと思います。

また、親は SomeCollection のように多数の MyItem を含むことができるため、親から子を取得するには何らかのページングが必要だと感じています。これにより、MyItems を参照する SomeCollection のプロパティを保持できなくなります。遅延ロードされているかどうかに関係なく、常に「オール オア ナッシング」です (そうですか?)。

ただし、データベース内のマッピング テーブルの形式で、MyItem エンティティとその親の間の参照が必要なのは間違いありません。

質問:

  • このマッピングを作成するにはどうすればよいですか? マッピングを行うことはできますか、それとも関係をビジネス ロジックに保持する必要がありますか?
  • SomeCollection に存在する MyItem エンティティを照会するにはどうすればよいですか? ICriteria を使用してデータベースに 1 回アクセスするだけでこれを実行できますか?
4

2 に答える 2

1

多対 1 の
親にはプロパティ Child が含まれており、子は複数の親からリンクされている場合があります。

class Parent
{
    public virtual MyItem Child { get; set; }
}

<class name="Parent">
    <many-to-one name="Child" column="MyItemId" />
</class>

結合テーブルを使用した多対多
親には子のコレクションが含まれ、子は複数の親からリンクされている場合があります。

class Parent
{
    public virtual IList<MyItem> Children { get; set; }
}

<class name="Parent">
    <bag name="Children" table="parent_myitem">
        <key column="parentid" />
        <many-to-many class="MyItem" column="MyItemId" />
    <bag>
</class>

基準クエリ

// find Parent with child named "foo".
DetachedCriteria.For<Parent>()
    .CreateAlias("Child", "c")
    .Add(Restrictions.Eq("c.Name", "foo"));

// find Parent with particular child
DetachedCriteria.For<Parent>()
    .Add(Restrictions.Eq("Child", child ));


// find Parent with one of children named "foo".
DetachedCriteria.For<Parent>()
    .CreateAlias("Children", "c")
    .Add(Restrictions.Eq("c.Name", "foo"));

// find a "page" of children for a parent
DetachedCriteria.For<Parent>()
    .Add(Restrictions.Eq("Id", parent.Id ))
    .CreateAlias("Children", "c")
    .SetFirstResult( 1041 )
    .SetMaxResults( 20 )
    .GetExecutableCriteria( session )
    .List<MyItem>();

最後のクエリは、最初のアクセス時に子コレクション全体を遅延読み込みし、その後の「ページ」でそれにインデックスを付けるだけで、より効率的に実行される場合とされない場合があります。データと使用状況によって異なります。

子コレクションが巨大になることをアプリオリに知っていない限り、最初に遅延ロード ルートを使用します。タイミングとプロファイリングが深刻な遅さを示している場合は、Criteria メソッドに切り替えます。

于 2010-03-04T11:42:12.643 に答える
0

あなたのようなケースがありました。グローバル構成、プロジェクト固有の構成、またはユーザー固有の構成のいずれかになる構成クラスがありました。私がしたことはこれでした:

  1. いずれにせよ、通常のように親をすべての可能な親にマップします(グローバルを除き、すべてに適用されることを意味するため、親はありません)
< class name="ConfigurationDomain" table="configuration">  
    < property name="ProjectId" column="project_id" type="int" insert="false" update="false" />  
    < property name="UserId" column="user_id" type="int" insert="false" update="false" />  
    < many-to-one name="Project" column="project_id" lazy="false" />  
    < many-to-one name="User" column="estimator_id" lazy="false" />
< /class>  
  1. 可能なすべての親のコレクションとして構成をマップします
< class name="UserDomain" table="user">  
    < set name="ConfigurationList" lazy="true" cascade="all-delete-orphan">  
      < key column="user_id" />  
      < one-to-many class="ConfigurationDomain" />  
    < /set>  
< /class>  

< class name="ProjectDomain" table="user">  
    < set name="ConfigurationList" lazy="true" cascade="all-delete-orphan">  
      < key column="project_id" />  
      < one-to-many class="ConfigurationDomain" />  
    < /set>  
< /class>

そのように、それは私のために働きました。たとえば、ID 55 のユーザーの構成にアクセスする方法は次のとおりです。

someUser.ConfigurationList は遅いので使用しません。HQL でこれを実行できるように、親のみをマップします (はるかに高速です)。

select c from ConfigurationDomain c where c.UserId=55

グローバル構成を取得するには、次のようにします。

select c from ConfigurationDomain c where (c.UserId IS NULL) and (c.ProjectId IS NULL)

振り返ってみると、HQL を使用することにした場合は、コレクション マッピングを削除することもできると思います。

注: 私は NHibernate で初期の頃に Criteria を使用していましたが、その後、HQL の方がやや強力であることがわかりました。他の人はこれについて異なる意見を持っているかもしれません。

于 2010-03-05T16:11:42.713 に答える