在Nhibernate中使用外键关系映射复合主键

时间:2010-12-21 18:17:39

标签: oracle nhibernate nhibernate-mapping composite-key multiple-columns

我正在为之工作的公司正在使用ERP,它的遗留数据库是Oracle。 到目前为止,我已经使用了包(oracle存储过程)来访问数据,但是在这些年里,数字一直在增长,现在我再也无法管理它了。
我试图用Nhibernate做一些实验并开始映射几张表 所有表都有复合主键。 简要说明:

表格顺序(表格名称: OCSAORH

OCHORDN( PK )=> ORDERNUMBER
OCHAMND( PK
OCHCOSC( PK )=>公司
OCHCLII
......

表OrderLine(表名: OCSALIN

OCLORDN( PK )=> ORDERNUMBER
OCLAMND( PK
OCLCOSC( PK )=>公司
OCLLINN( PK )=>行号
OCLSSEQ( PK
OCLITMN
...

这是我的映射

顺序

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MvcOracleNhibernate"
                   namespace="MvcOracleNhibernate.Domain">
  <class name="Order" table="OCSAORH">
    <composite-id>
      <key-property name="Number" column="OCHORDN"></key-property>
      <key-property name="Ver" column="OCHAMND"></key-property>
      <key-property name="Company" column="OCHCOSC"></key-property>
    </composite-id>
    <property name="CustomerCode" column="OCHCLII" type="String" length="10"></property>
    <property name="Reference" column="OCHOCNO" type="String" length="25"></property>
    <property name="Date" column="OCHOCDT" type="Double"></property>
    <bag name="OrderLines" cascade="all-delete-orphan" generic="true" inverse="true" lazy="false">
      <key>
        <column name="OCLORDN" not-null="true"/>
        <column name="OCLAMND" not-null="true"/>
        <column name="OCLCOSC" not-null="true"/>
      </key>
      <one-to-many class="OrderLine" not-found="ignore"/>
    </bag>
  </class>
</hibernate-mapping>

订单行

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MvcOracleNhibernate"
                   namespace="MvcOracleNhibernate.Domain">
  <class name="OrderLine" table="OCSALIN">
    <composite-id>
      <key-property name="Number" column="OCLORDN"></key-property>
      <key-property name="Ver" column="OCLAMND" ></key-property>
      <key-property name="Company" column="OCLCOSC"></key-property>
      <key-property name="Line" column="OCLLINN"></key-property>
      <key-property name="Seq" column="OCLSSEQ"></key-property>
    </composite-id>
    <property name="Item" column="OCLITMN" type="String" length="19"></property>
    <property name="Quantity" column="OCLQTYP" type="Double"></property>
  </class>
</hibernate-mapping>

通过这些映射,一切正常;我可以加载订单,延迟加载加载我的行。 在阅读一些文档时,我注意到我没有定义多对一关系,所以我添加了这个:

<many-to-one name="Order" class="Order" lazy="proxy">
  <column name="OCHORDN" not-null="true"/>
  <column name="OCHAMND" not-null="true"/>
  <column name="OCHCOSC" not-null="true"/>
</many-to-one>   

到OrderLine映射文件。
现在,如果我运行我的测试应用程序,订单已正确加载,但订单行未加载 我得到 {NHibernate.ADOException} = {“无法初始化集合:...} 我试图调查并注意到生成的查询检索行是错误的。这是SQL:

SELECT 
    orderlines0_.OCLORDN as OCLORDN1_, 
    orderlines0_.OCLAMND as OCLAMND1_, 
    orderlines0_.OCLCOSC as OCLCOSC1_, 
    orderlines0_.OCLLINN as OCLLINN1_, 
    orderlines0_.OCLSSEQ as OCLSSEQ1_, 
    orderlines0_.OCLORDN as OCLORDN13_0_, 
    orderlines0_.OCLAMND as OCLAMND13_0_, 
    orderlines0_.OCLCOSC as OCLCOSC13_0_, 
    orderlines0_.OCLLINN as OCLLINN13_0_, 
    orderlines0_.OCLSSEQ as OCLSSEQ13_0_, 
    orderlines0_.OCLITMN as OCLITMN13_0_, 
    orderlines0_.OCLQTYP as OCLQTYP13_0_, 
    orderlines0_.OCHORDN as OCHORDN13_0_, 
    orderlines0_.OCHAMND as OCHAMND13_0_, 
    orderlines0_.OCHCOSC as OCHCOSC13_0_ 
FROM OCSALIN orderlines0_ 
WHERE 
    orderlines0_.OCLORDN=? 
    and orderlines0_.OCLAMND=? 
    and orderlines0_.OCLCOSC=?

您可以注意到select的最后3个字段(具有前缀OCH而不是OCL的字段)不是OCSALIN表的成员;它们是OCSAORH的关键 阅读文档和示例1天后,我无法弄清楚我做错了什么 那里有人可以尝试帮忙吗?

1 个答案:

答案 0 :(得分:2)

这是预期的行为。您在多对一映射中定义了外键。因此,列需要存在于您定义的对象中。

我想你想要这个

<many-to-one name="Order" class="Order" lazy="proxy">
  <column name="OCLORDN" not-null="true"/>
  <column name="OCLAMND" not-null="true"/>
  <column name="OCLCOSC" not-null="true"/>
</many-to-one>