Как я могу отобразить "insert = 'false' update = 'false'" на ключ-свойство составного идентификатора, который также используется в FK «один ко многим»? - PullRequest
40 голосов
/ 04 февраля 2011

Я работаю на базе устаревшего кода с существующей схемой БД.Существующий код использует SQL и PL / SQL для выполнения запросов к БД.Перед нами была поставлена ​​задача сделать небольшую часть независимой от движка базы данных проекта (сначала все изменить в конце концов).Мы решили использовать файлы отображения Hibernate 3.3.2.GA и "* .hbm.xml" (в отличие от аннотаций).К сожалению, невозможно изменить существующую схему, потому что мы не можем регрессировать какие-либо унаследованные функции.

Проблема, с которой я сталкиваюсь, заключается в том, когда я пытаюсь отобразить однонаправленные отношения «один ко многим», гдеФК является также частью составного ПК.Вот классы и файл сопоставления ...

CompanyEntity.java

public class CompanyEntity {
    private Integer id;
    private Set<CompanyNameEntity> names;
    ...
}

CompanyNameEntity.java

public class CompanyNameEntity implements Serializable {
    private Integer id;
    private String languageId;
    private String name;
    ...
}

CompanyNameEntity.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.example">

    <class name="com.example.CompanyEntity" table="COMPANY">
        <id name="id" column="COMPANY_ID"/>
        <set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false">
            <key column="COMPANY_ID"/>
            <one-to-many entity-name="vendorName"/>
        </set>
    </class>

    <class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME">
        <composite-id>
            <key-property name="id" column="COMPANY_ID"/>
            <key-property name="languageId" column="LANGUAGE_ID"/>
        </composite-id>
        <property name="name" column="NAME" length="255"/>
    </class>

</hibernate-mapping>

Этот код прекрасно работает для SELECT и INSERT компании с именами.Я столкнулся с проблемой при попытке обновить существующую запись.Я получил BatchUpdateException и после просмотра журналов SQL я увидел, что Hibernate пытается что-то сделать глупо ...

update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=?

Hibernate пытается отключить дочерние записи перед их обновлением,Проблема заключается в том, что это поле является частью PK и не может обнуляться.Я нашел быстрое решение заставить Hibernate не делать этого, добавив not-null = 'true' к элементу "key" в родительском отображении.Так что теперь отображение может выглядеть следующим образом ...

CompanyNameEntity.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.example">

    <class name="com.example.CompanyEntity" table="COMPANY">
        <id name="id" column="COMPANY_ID"/>
        <set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false">
            <key column="COMPANY_ID" not-null="true"/>
            <one-to-many entity-name="vendorName"/>
        </set>
    </class>

    <class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME">
        <composite-id>
            <key-property name="id" column="COMPANY_ID"/>
            <key-property name="languageId" column="LANGUAGE_ID"/>
        </composite-id>
        <property name="name" column="NAME" length="255"/>
    </class>

</hibernate-mapping>

Это отображение дает исключение ...

org.hibernate.MappingException: Repeated column in mapping for entity: companyName column: COMPANY_ID (should be mapped with insert="false" update="false")

Моя проблема сейчасЯ пытался добавить эти атрибуты в элемент key-property, но это не поддерживается DTD.Я также попытался изменить его на элемент «ключ ко многим к одному», но это тоже не сработало.Итак ...

Как мне сопоставить "insert = 'false' update = 'false'" с ключевым свойством составного идентификатора, которое также используется в FK «один ко многим»?

Ответы [ 2 ]

83 голосов
/ 18 февраля 2011

Я думаю, что вы ищете аннотацию:

public class CompanyName implements Serializable {
//...
@JoinColumn(name = "COMPANY_ID", referencedColumnName = "COMPANY_ID", insertable = false, updatable = false)
private Company company;

И вы должны иметь возможность использовать аналогичные отображения в файле hbm.xml, как показано здесь (в 23.4.2):

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-mappings.html

0 голосов
/ 21 ноября 2016

"Dino TW" предоставил ссылку на комментарий. Исключение отображения Hibernate: повторяющийся столбец в отображении для объекта , который содержит важную информацию.

Ссылка намекает на предоставление "inverse = true" в отображении набора, я пробовал, и это на самом деле работает. Это такая редкая ситуация, когда клавиши Set и Composite собираются вместе. Сделайте инверсию = true, мы оставляем вставку и обновление таблицы с помощью составного ключа, чтобы они позаботились сами.

Ниже может быть необходимое отображение,

<class name="com.example.CompanyEntity" table="COMPANY">
    <id name="id" column="COMPANY_ID"/>
    <set name="names" inverse="true" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false">
        <key column="COMPANY_ID" not-null="true"/>
        <one-to-many entity-name="vendorName"/>
    </set>
</class>
...