我遇到了以下代码中多对一映射的问题:
...
<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
请帮忙......
谢谢,
答案 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)
尝试两件事
Session.Dispose
刷新会话,否则使用Flush()
NHibernate将为您创建ID并尝试管理它们,除非您明确告知它。