1

假设我有一个名为 MyItem 的实体。它可以包含在许多“父母”中,例如 SomeCollection 和 SomeOtherCollection。因为它可以包含在许多父母中,并且由于我不希望 MyItem 了解父母,所以我希望 MyItem 中没有任何属性引用父母。

而且由于像 SomeCollection 这样的父级可以包含许多 MyItem,我觉得我需要进行某种分页来从父级获取子级。这将使我无法在 SomeCollection 中拥有引用 MyItems 的属性。无论是否延迟加载,它总是“全有或全无”(对吧?)。

不过,我肯定需要在 MyItem 实体和它们的父实体之间进行一些引用,以数据库中映射表的形式。

问题:

  • 如何为此创建映射?我可以有映射,还是应该将关系保留在业务逻辑中?
  • 如何查询 SomeCollection 中存在哪些 MyItem 实体?我可以只使用 ICriteria 访问一次数据库吗?
4

2 回答 2

1

多对一
Parent 包含一个属性 Child,孩子可能来自多个父母。

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

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

Many-to-Many with a join table
Parent 包含一个 Child 的集合,这些孩子可能来自多个父母。

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. 在任何情况下,我都会像往常一样将 Parent 映射到所有可能的父级(全局除外,这意味着应用于所有父级,因此没有父级)
< 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 回答