четверг, 5 февраля 2009 г.

Hibernate. Атрибут inverse

При работе с Hibernate часто ли вы задумываетесь зачем и для чего нужен атрибут inverse и что означает inverse = "true"? В данной заметке будут раскрыта эта тема.


По существу, "inverse" обозначает какой конец отношения должен игнорироваться. Когда вы сохраняете предка, имеющего коллекцию потомков, должны ли вы спрашивать предка о его потомках, или же спрашивать потомков, кто является их предком?

Итак взгляните на код:
Parent parentA = new Parent();
Parent parentB = new Parent();
Child child = new Child();
parentA.getChildren().add(child); // с помощью самого предка
child.setParent(parentB); // с помощью установления предка у потока

как hibernate сохранит эту ситуацию? Для однонаправленной связи one-to-many это очевидно; только один конец отношения создаётся (это только parent.addChild(), не child.setParent()), но когда связь является двунаправленной (parent.getChild и child.getChildren), то вы должны указать, является ли one-to-many обратным(inverse) или нет.

Что значит быть обратным? Это информирует hibernate, что нужно игнорировать конец отношения. Если отношение one-to-many отмечено, как обратное, hibernate будет создавать child-> parentB отношение (child.getParent). Если one–to–many отношение не было помечено, как обратное, тогда child->parentA отношение будет создано.


Просто запомните следующую вещь:
  • если inverse = "true" на one–to–many, тогда child.getParent будет вызван.
  • если inverse = "false" на one–to–many, тогда parent.getChildren будет вызван.

4 комментария:

  1. извини, но ничего не понятно... это при том, что я немного разбираюсь в хибернейте

    ОтветитьУдалить
  2. Ладно, тогда объясню короче и на примере.
    Представим такой абстрактный пример. Есть студенты и группы. Один студент может содержаться только в одной группе(поставим такое жесткое ограничение).

    Как нам это дело замаппить?

    1) Мы можем вынести связь "Студенты-Группы" в отдельную таблицу. В этой таблице будет 2 колонки. Все вроде бы понятно, это стандартный способ маппить множества.

    2) Но мы можем обойтись и без дополнительной таблицы, потому что нам по задаче известно, что каждый студент содержится ровно в одной группе. Тогда логично сделать у студента атрибут "Группа".

    Но как тогда у группы выбирать всех студентов? Маппинг группы как-то должен знать, что у студента есть колонка "Группа". Тогда мы определяем у группы множество с атрибутом "inverse=true" и указанием по какой колонке в студенте нужно смотреть.

    Таким образом мы обходимся без доп. таблицы и все счастливы :)

    ОтветитьУдалить
  3. Я вот очень плотно столкнулся с inverse="false"

    Есть сущности - "язык" и "пользователь"
    Каждый пользователь может
    1) знать язык
    2) учить язык
    выходит, у меня двойная связь многие-ко-многим.
    Итого, с учетом перехода к связям один-ко-многим получается 4 таблицы.


    Гинерил маппиги в NetBeans по готовой базе.
    Маппинг по юзеру:





















    но нетбинс, изначально, создал один set с inverse="false" а другой с inverse="true"
    в итоге у меня при создании пользователя добавлялись только те языки которые он знал.

    ОтветитьУдалить
  4. Поэтому хорошим тоном при создании двусторонней ассоциации является заполнять ОБА конца связи.

    ОтветитьУдалить