Сопоставление составного первичного ключа с отношением внешнего ключа в Nhibernate

компания, в которой я работаю, использует ERP, а ее устаревшая база данных - Oracle. До сих пор я использовал пакеты (хранимые процедуры Oracle) для доступа к данным, но с годами их число постоянно росло, и теперь я больше не могу ими управлять.
Я пытался провести несколько экспериментов с Nhibernate и начал отображать несколько таблицы.
Все таблицы имеют составные первичные ключи. Короткое описание:

Порядок таблиц (название таблицы: OCSAORH)

OCHORDN (PK) => Номер заказа
OCHAMND (PK)
OCHCOSC (PK) => Компания
OCHCLII < br> ...

Таблица OrderLine (имя таблицы: OCSALIN)

OCLORDN (PK) => Номер заказа
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>

OrderLine:

<?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} = {"не удалось инициализировать collection: ...} Я попытался исследовать и заметил, что сгенерированный запрос на получение строк неверен. Это 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=?

Как вы можете заметить, последние 3 поля выбора (с префиксом OCH вместо OCL) не являются членами таблицы OCSALIN; они - ключ к OCSAORH.
После 1 дня, проведенного за чтением документации и примеров, я не могу понять, что делаю неправильно.
Есть ли там кто-нибудь, кто может попытаться помочь?


person LeftyX    schedule 21.12.2010    source источник


Ответы (1)


Это ожидаемое поведение. Вы определяете внешние ключи в сопоставлении «многие к одному». Таким образом, столбцы должны существовать в объекте, который вы определяете.

Я думаю ты хочешь этого

<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>   
person Vadim    schedule 21.12.2010
comment
Работает как часы. Спасибо, Ядс. У вас есть ссылки на документы, где я могу почитать об этом подробнее? Еще раз спасибо. - person LeftyX; 22.12.2010
comment
@vandalo Я на самом деле пользователь NHibernate, но на самом деле это порт Hibernate, поэтому они очень похожи. Я бы начал здесь hibernate.org/docs и прочитал справочное руководство, чтобы понять, как отображение файлы работают. После этого просто практика, практика, практика;) - person Vadim; 22.12.2010
comment
Спасибо, я начал с официальной документации, но у меня нет времени читать все документы. Есть так много уловок и вещей, которые нужно знать. - person LeftyX; 22.12.2010
comment
@vandalo Если есть одна глава, которую стоит прочитать, это глава 5: Базовое отображение O / R docs.jboss.org/hibernate/core/3.6/reference/en-US/html/ - person Vadim; 22.12.2010