Nhibernate多对一的问题

时间:2010-01-20 11:40:05

标签: nhibernate

我遇到了以下代码中多对一映射的问题:

...                 

<property name ="CustomerID"/>    

<!-- Many-to-one mapping: Customer -->
<many-to-one name="Customer" 
                 class="Customer" 
                 column="CustomerID"
                 insert="false" update="false"/>
<property name="Date" />

...

您可能会注意到我已将两个CustomerID映射到Customer表。我这样做的原因是因为当我想创建一个Order时,我只是将值分配给CustomerID和其他需求字段然后保存。多对一映射,我只想获得每个customerID的详细信息。

但问题是:在我使用Session.Flush()更新订单和Executre SaveOrUpdate的customerID之后(我正在使用HibernateTemplate),在访问Order.Customer时我仍然得到了旧图。 即:

Order = getOderByID(1);
Order.CustomerID = 3 //假设CustomerId的值为1.现在我改为3
SaveOrUpdate(订单);
打印(Order.Customer.CustomerID)//它返回1,这是错误的。它应该是3

请帮忙......

谢谢,

3 个答案:

答案 0 :(得分:3)

我建议你从NHibernate的角度来看待这个问题。而不是从关系数据库视图。让我从我认为你应该做的事情开始。

var customer = session.Load<Customer>(3);
var order = session.Load<Order>(1);
order.Customer = customer; 

//assuming this is a one directional mapping. otherwise you might 
//have to do some more steps to disassociate the order from the old 
//customers collection and add it to the new customers collection

session.SaveOrUpdate(order);

现在,order.Customer.CustomerID将返回3.

正如Serkan所说,使用对象而不是主键更好,更可行。

此外,这里确实不会有任何性能影响。只要类具有虚拟公共方法,Nhibernate就能够代理很多关联。因此,只要您只查询客户的Id,就不会生成单独的SQL查询。 Id已经存在代理对象。

关于原始问题,我有预感。 NHibernate动态生成更新和插入的sql查询。这个案例是一个更新。您已将CustomerID属性显式设置为3.但订单对象的Customer属性仍指向Id 1的客户对象。因此,当NHibernate生成sql查询时,它会尝试将值首先设置为1,如您所要求的那样它来。然后它还看到Customer仍然指向旧对象,因此将CustomerId属性重置为1.我认为NHibernate与双映射混淆。

你可以做两件事。首先在NHibernate配置中启用“show_sql”属性。

<nhibernate>
  ...
  <add key="hibernate.show_sql" value="true" />
</nhibernate>

检查保存订单时生成的sql是什么。这将更好地解释事情。

其次,保存订单后,执行session.Refresh(order);您可以阅读有关Refresh()方法here的信息。它在第9.2节末尾。它将使用数据库中的新值重新加载订单对象。调用order.CustomerID应该显示您在数据库中存储的值。

答案 1 :(得分:1)

如果你在完成OR映射后试图忘记实体的Id,我认为从长远来看你会感到更快乐。你处于一个不同的层面,你应该只考虑对象。如果我是你,我会一起删除CustomerId属性。

如果遇到性能问题,请尝试以NHibernate方式解决它们,缓存等。

答案 2 :(得分:0)

尝试两件事

  1. 如果是{2.}},则通过Session.Dispose刷新会话,否则使用Flush()
  2. 分配您的ID客户端。
  3. NHibernate将为您创建ID并尝试管理它们,除非您明确告知它。