假设我有两个持久性类Cat
和Hat
。让我们假设两者之间的关系是双向一对多的,因为在Cat中可以有许多不同的帽子,我们可以在两个方向上遍历映射。为了在每个类的实例之间创建关联,我应该能够并且如果我错了就纠正我,请执行以下操作:
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 documentation,但仍然无法使其正常工作。我做错了什么?
下面填写完整的地图文件:
Cat.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>
Hat.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>
修改
我认为问题在于我没有初始化Cat类中的ISet<Hat>
值。但是,我遇到了一个新问题。当我尝试访问关联时,我收到此错误:
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;
}
这会产生相同的“无会话”错误。我很难过。
答案 0 :(得分:0)
您需要在hat.hbm中添加多对一条目。 我认为应该有效。
然后你必须设置关联的两面
whiskers.Hats.Add(REDHAT);
redHat.Cat =晶须;
我认为这样可以使你的样本有效。
您的“无会话”问题的原因是,集合代理仅适用于创建它的会话。因此,在您的示例中,它仅适用于创建Hat实例的会话。可以将代理与另一个会话连接,但通常不会推荐,因为它对事务边界和数据一致性有复杂的影响。
答案 1 :(得分:0)
我通过创建一个SessionManager解决了这个问题,它允许我打开一个Session,执行任何事务并访问Session singleton中的任何集合代理,然后关闭Session。