Nhibernate多对一问题 [英] Nhibernate many-to-one problem

查看:71
本文介绍了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表.我这样做的原因是,当我要创建订单时,我只将值分配给CustomerID,然后将其他require字段保存即可.多对一映射,我只想获取每个customerID的详细信息.

但是,问题在于:在我更新了Order的customerID并也使用Session.Flush()执行Executre SaveOrUpdate(我正在使用HibernateTemplate)之后,访问Order.Customer时我仍然得到了原来的数字. 即:

Order = getOderByID(1);
Order.CustomerID = 3//假设CustomerId的值为1.现在我更改为3
SaveOrUpdate(Order);
Print(Order.Customer.CustomerID)//返回1,这是错误的.应该是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()方法的信息此处.它即将在9.2节的结尾.它将使用数据库中的新值重新加载订单对象.调用order.CustomerID应该显示您已存储在数据库中的值.

I've got a problem with mapping many-to-one in the following code:

...

<property name ="CustomerID"/>    

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

...

You may notice that i have mapped two CustomerID to Customer table. The reason i do this because when i want to create an Order, i just only assign value to CustomerID and other require fields then do save. many-to-one mapping, I just want to get detail of each customerID.

But, the problem is that: after i update customerID of an Order and Executre SaveOrUpdate with Session.Flush() also (I'm using HibernateTemplate), i still got the old figure when accessing to Order.Customer. i.e:

Order = getOderByID(1);
Order.CustomerID=3 // Suppose value of CustomerId is 1. Now I changed to 3
SaveOrUpdate(Order);
Print(Order.Customer.CustomerID)// it returns 1 which is wrong. It should be 3

Pls help...

Thanks,

解决方案

I would suggest you to look at this problem from an NHibernate point of view. And not from a relational database view. Let me start with what i feel you should be doing.

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);

Now, order.Customer.CustomerID will return 3.

As Serkan suggested, its better and more feasible to work with objects instead of primary keys.

Also, there really shouldnt be any performance impact here. Nhibernate is able to proxy a lot of the associations as long as the classes have virtual public methods. Because of this, as long as you only query for the Id of the customer, it will not generate a separate sql query. The Id is already there with the proxy object.

With regards to the original question, I have a hunch. NHibernate dynamically generates the sql query for the update and the inserts. This case here is of an update. You have explicitly set the CustomerID property to 3. But the Customer property of the order object still points to the customer object with Id 1. So, when NHibernate generates the sql query, it trys to set the value first to 1, as you asked it to. Then it also sees that the Customer is still pointing to the old object, so reset the CustomerId property to 1. I think NHibernate is getting confused with the dual mappings.

There are two things that you can do. First enable the "show_sql" property in the NHibernate configuration.

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

Check what is the sql being generated when you save the order. That will explain things better.

Second, after saving the order, do session.Refresh(order); You can read about the Refresh() method here. Its towards the end of the section 9.2. It will reload the order object with fresh values from the database. Calling order.CustomerID should show what value you have stored in the database.

这篇关于Nhibernate多对一问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆