Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Hibernate many-to-many + свойства связи


Автор: 3x15 9.10.2007, 15:30
Здравствуйте!

Реляционные БД имеют конкретные решения для каждого случая. Было бы правильно описать все случаи в HIBERNATE. И можно было бы проще все решать.

А сучай такой.
Есть таблица - в ней записи связаны друг с другом many-to-many. Это пример иерархии в которой один элемент может быть в однум случае главным в другом зависимым, при этом не один раз.

В реляционных БД решение это отдельная таблица "field_field" типа:

id | id_parent | id_chield

Все красиво ложится в Hiber:


Код

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="hField" table="fields">
        <id name="id" column="id" access="field">
            <generator class="native"/>
        </id>

        <property name="name" column="name" not-null="false"/>

        <set name="chield" cascade="save-update" table="field_field">
            <key  not-null="true" update="true" column="idfield"/>
            <many-to-many column="idfield_chield" class="hField"/>
        </set>
        <set name="parent" cascade="save-update" table="field_field">
            <key  not-null="true" update="true" column="idfield_chield"/>
            <many-to-many column="idfield" class="hField"/>
        </set>
    </class>
</hibernate-mapping>


и даже работает!!! smile

Но важно еще описать каждую связь определнными свойствами, т.е. добавить поля в таблицу "field_field". Например, порядковый номер, описание. Получится:
id | id_parent | id_chield | number | description

И внимаение вопрос! Как описать эти свойства в HIBERNATE?

Можно отдельной сущностью, но это не красиво и затратно по коду, должно быть готовое, красивое решение, т.к. задача стандартная...

Спасибо...

Автор: mindflyer 10.10.2007, 15:05
Цитата(3x15 @  9.10.2007,  15:30 Найти цитируемый пост)
Но важно еще описать каждую связь определнными свойствами, т.е. добавить поля в таблицу "field_field". Например, порядковый номер, описание. Получится:
id | id_parent | id_chield | number | description

И внимаение вопрос! Как описать эти свойства в HIBERNATE?

Можно отдельной сущностью, но это не красиво и затратно по коду, должно быть готовое, красивое решение, т.к. задача стандартная...


А как ты в java собираешься задавать дополнительные характеристики связи? Т.е. какую структуру хочешь сохранять и восстанавливать? Если это обыкновенная коллекция, то тебе их и в java негде хранить.
В этом случае нужна именно отдельная сущность.

Автор: 3x15 15.10.2007, 15:33
Здравствуйте!

Да в яве надо писать отдельный класс. Но если его отмапить в Хибернэйт, то невозможно будет делать операции с изменениями (например, вставка новых связей), т.к. Хибернэйт просит поставить update="false" insert="false". Т.е. все что уже есть в базе красиво мапится и извлекается, но новую связь организовать не могу.

В ФАК-ах по Хибернэйту такой случа рассматривается:

I have a many-to-many association between two tables, but the association table has some extra columns (apart from the foreign keys). What kind of mapping should I use?

Use a composite-element to model the association table. For example, given the following association table: 

Код

create table relationship ( 
    fk_of_foo bigint not null, 
    fk_of_bar bigint not null, 
    multiplicity smallint, 
    created date )


you could use this collection mapping (inside the mapping for class Foo):

Код

<set name="relationship">
    <key column="fk_of_foo"/>
    <composite-element class="Relationship">
        <property name="multiplicity" type="short" not-null="true"/>
        <property name="created" type="date" not-null="true"/>
        <many-to-one name="bar" class="Bar" not-null="true"/>
    </composite-element>
</set>


You may also use an <idbag> with a surrogate key column for the collection table. This would allow you to have nullable columns.

An alternative approach is to simply map the association table as a normal entity class with two bidirectional one-to-many associations.

Но в этом варианте тоже не могу создать новую свзяь. И перед тем как выдать ошибку он сначала удалет все существующие связи у главного узла, затем их снова восстанавливает, короче что-то не так.

Проблема не решена... :(

Автор: mindflyer 16.10.2007, 15:57
Цитата(3x15 @  9.10.2007,  15:30 Найти цитируемый пост)
Можно отдельной сущностью, но это не красиво и затратно по коду, должно быть готовое, красивое решение, т.к. задача стандартная...

ИМХО, стандартное решение - это именно отдельная сущность в базе данных. 

Цитата(3x15 @  15.10.2007,  15:33 Найти цитируемый пост)
Проблема не решена... :(

У тебя в java - три класса, в базе данных - три таблицы. Ты хочешь сделать маппинг трёх классов на три таблицы через две сущности hibernate? Зачем так усложнять? Чего ты хочешь добиться?

Добавлено через 1 минуту и 49 секунд
Цитата(3x15 @  15.10.2007,  15:33 Найти цитируемый пост)
Да в яве надо писать отдельный класс. Но если его отмапить в Хибернэйт, то невозможно будет делать операции с изменениями (например, вставка новых связей), т.к. Хибернэйт просит поставить update="false" insert="false". Т.е. все что уже есть в базе красиво мапится и извлекается, но новую связь организовать не могу.

Что значит не можешь организовать?

Автор: 3x15 17.10.2007, 09:59
Здравствуйте!

Заработало, до концпа сам не понял... smile
Всего две таблицы. Все связи, описанные во второй таблице вяжут записи первой таблицы.

Всего 2 класса в яве. для первой таблице и для второй. Вот как это выглядит в Хибернэйте:

Код

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="hField" table="fields">
        <id name="id" column="id" access="field">
            <generator class="native"/>
        </id>

        <property name="name" column="name" not-null="false"/>

        <set name="fields" table="field_field" order-by="sort" lazy="true">
            <key column="parent" not-null="true"/>
            <one-to-many entity-name="hS" />
        </set>

        <set name="fieldsParent" table="field_field" order-by="sort" lazy="true">
            <key column="chield" not-null="true"/>
            <one-to-many entity-name="hS" />
        </set>
    </class>
</hibernate-mapping>




<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="hS" table="field_field" lazy="true">
        <id name="id" column="id" access="field">
            <generator class="native"/>
        </id>

        <property name="sort" column="sort"/>

        <many-to-one name="chield" class="hField" column="chield" insert="false" update="false"/>
        <many-to-one name="parent" class="hField" column="parent" insert="false" update="false"/>

    </class>
</hibernate-mapping>


Вот все мое непонимание было как можно создать запись в hS если стоит insert="false" update="false"
Оказывается можно smile

Добавлено через 1 минуту и 45 секунд

И еще непонимаение было в том, что в моем случае это не связь много ко многим... smile


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)