0

假设我有两个持久类CatHat. 让我们想象一下,两者之间的关系是双向的一对多,因为在一只猫中可以有许多不同的帽子,我们可以在两个方向上遍历映射。为了在每个类的实例之间创建关联,如果我错了,我应该能够并纠正我,执行以下操作:

Cat whiskers = new Cat();
Hat redHat = new Hat();
redHat.Id = 1; // normally assigned by generator but this makes example more explicit
whiskers.Hats.Add(redHat);
catService.Save(whiskers);
hatService.Save(redHat);

考虑到这一点,我是否应该无法通过执行以下操作来检索与 redHat 关联的 Cat?

Hat hat = hatService.FindById(1); // redHat has Id 1
Cat cat = hat.Cat; // cat should be whiskers

不幸的是,当我尝试使用这种技术时,cat 结果在最后一行是一个空对象。我猜我在 Cat.hbm.xml 中的一对多映射中遗漏了一些东西,或者至少我希望它是那么简单的东西。这是它目前的样子:

<set name="Hats" inverse="true">
  <key column="Id"/>
  <one-to-many class="Hat"/>
</set>

我在 Hat.hbm.xml 中没有映射,因为添加一个会导致“重复映射”错误。我阅读了有关关联映射的 Hibernate文档,但仍然无法正常工作。我究竟做错了什么?

完整的映射文件如下:

猫.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="Domain"
               namespace="Domain">

  <class name="Cat" table="cats" lazy="true">

    <id name="Id">
      <generator class="increment" />
    </id>

    <property name="Name" />

    <set name="Hats" inverse="true">
      <key column="Id"/>
      <one-to-many class="Hat"/>
    </set>

  </class>

</hibernate-mapping>

帽子.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="Domain"
               namespace="Domain">

  <class name="Hat" table="hats" lazy="true">

    <id name="Id">
      <generator class="increment" />
    </id>

  </class>

</hibernate-mapping>

编辑

我认为问题在于我没有初始化ISet<Hat>Cat 类中的值。但是,我遇到了一个新问题。当我尝试访问关联时,出现此错误:

Could not initialize proxy - no Session.

我想如果我在我的 DAO 中创建一个方法,我可以很容易地避免这种情况,我可以将它包装在这样的会话中:

public Cat GetRelatedCat(Hat hat)
{
    Cat cat;
    using (ISession session = HibernateUtil.GetSessionFactory().OpenSession())
    {
        cat = hat.Cat;
    }
    return cat;
}

这会产生相同的“无会话”错误。我难住了。

4

2 回答 2

0
  1. 您需要在 hat.hbm 中添加多对一条目。我认为应该工作。

  2. 然后你必须设置关联的双方

    胡须.帽子.Add(redHat);

    redHat.Cat=胡须;

我认为这应该使您的示例工作。

您的“无会话”问题的原因是,集合代理仅适用于创建它的会话。因此,在您的示例中,它仅适用于创建您的 Hat 实例的会话。可以将代理与另一个会话连接,但通常不推荐这样做,因为它对事务边界和数据一致性有复杂的影响。

于 2011-01-13T08:32:01.260 回答
0

我通过创建一个 SessionManager 解决了这个问题,它允许我打开一个 Session,执行任何事务并访问 Session 单例中的任何集合代理,然后关闭 Session。

于 2011-01-16T02:59:45.087 回答