mappedby hibernate что это

Может кто-нибудь объяснить mappedBy в JPA и Hibernate?

Вот мои классы с аннотациями:

Авиакомпания :

AirlineFlights:

РЕДАКТИРОВАТЬ:

У AirlineFlights есть idAirline как ForeignKey, а у Airline нет idAirlineFlights. Это делает AirlineFlights владельцем / идентифицирующим лицом?

Теоретически я бы хотел, чтобы авиакомпания стала владельцем авиакомпании AirlinesFlight.

7 ответов

Это говорит Hibernate: «Пойдите и просмотрите свойство bean-компонента с именем« авиакомпания »на предмете, который у меня есть в коллекции, чтобы найти конфигурацию».

Вы начали с сопоставления ManyToOne, затем добавили сопоставление OneToMany для двунаправленного способа. Затем на стороне OneToMany (обычно это ваша родительская таблица / класс) вы должны указать «mappedBy» (сопоставление выполняется дочерней таблицей / классом и в дочерней таблице / классе), поэтому спящий режим не будет создавать таблицу сопоставления EXTRA в БД (например, TableName = parent_child).

Атрибут mappedBy характеризует двунаправленную связь и должен быть установлен на родительской стороне. Другими словами, для двунаправленной ассоциации @OneToMany установите mappedBy на @OneToMany на родительской стороне и добавьте @ManyToOne на дочерней стороне, на которую ссылается mappedBy. Через mappedBy двунаправленная ассоциация @OneToMany сигнализирует о том, что она отражает отображение дочерней стороны @ManyToOne.

Mappedby = «объект сущности того же класса, созданный в другом классе»

Например, Если мы применим сопоставление в классе Employee к объекту сотрудника, то внешний ключ из таблицы Employee будет удален.

Отношения между таблицами и отношениями сущностей

В системе реляционной базы данных отношение таблиц one-to-many выглядит следующим образом:

Обратите внимание, что связь основана на столбце внешнего ключа (например, post_id ) в дочерней таблице.

Если вы посмотрите на диаграмму выше, вы увидите, что есть два способа управлять этими отношениями.

В сущности Post у вас есть коллекция comments :

И в PostComment связь post отображается следующим образом:

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

MappedBy

Атрибут mappedBy сообщает, что сторона @ManyToOne отвечает за управление столбцом внешнего ключа, а коллекция используется только для выборки дочерних сущностей и для каскадирования изменений состояния родительской сущности дочерним элементам (например, удаление родитель также должен удалить дочерние объекты).

Синхронизируйте обе стороны двунаправленной ассоциации

Теперь, даже если вы определили атрибут mappedBy и дочерняя связь @ManyToOne управляет столбцом внешнего ключа, вам все равно необходимо синхронизировать обе стороны двунаправленной связи.

Методы addComment и removeComment обеспечивают синхронизацию обеих сторон. Итак, если мы добавляем дочернюю сущность, дочерняя сущность должна указывать на родительскую, а родительская сущность должна иметь дочернюю сущность, содержащуюся в дочерней коллекции.

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

Поэтому нам нужно указать спящему режиму, чтобы он выполнял сопоставление только с одной стороны и координировал их.

MappedBy сигнализирует спящему режиму, что ключ для отношения находится на другой стороне.

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

Источник

Связанные сущности в Hibernate

Статья является продолжением описания примера использования Sequence в Hibernate, в которой была рассмотрена только одна сущность и представлено описание сессии Session. В данной статье с использованием практического примера рассмотрим вопрос определения связей между сущностями.

Примечание : чтобы не вынуждать Вас обращаться к начальной статье, часть информации здесь будет повторена.

Классы в Java могут не только наследоваться друг от друга, но и включать в себя в качестве полей другие классы или коллекции классов. В столбцах таблиц БД нельзя хранить сложные составные типы и коллекции таких типов (за некоторыми исключениями). Это не позволяет сохранять подобный объект в одну таблицу. Но можно сохранять каждый класс в свою собственную таблицу, определив необходимые связи между ними. C описания связей между объектами и начнем.

Определение связей между сущностями

Для определения связей между сущностями Hibernate использует аннотации @OneToOne, @OneToMany, @ManyToOne, @ManyToMany.

@OneToOne

Для связи один к одному в обоих классах к соответствующим полям добавляется аннотация @OneToOne. Параметр optional говорит JPA, является ли значение в этом поле обязательным или нет. Связанное поле в User объявлено с помощью аннотации @JoinColumn, параметр name которой обозначает поле в БД для создания связи. Для того, чтобы объявить сторону, которая не несет ответственности за отношения, используется атрибут mappedBy в сущности Passport. Он ссылается на имя свойства связи (passport) на стороне владельца.

Связь в БД между таблицами users и passports осуществляется посредством поля passport_id в таблице users.

@OneToMany и @ManyToOne

Аннотации @OneToMany (один-ко-многим) и @ManyToOne (многие-к-одному) рассмотрим на примере гражданина и его места проживания. Гражданин имеет один основной адрес проживания, но по одному адресу могут проживать несколько человек. В следующем листинге представим эти сущности (лишние поля, не связанные с аннотациями, не отображаются) :

Владельцем в этом примере также будет класс Person, который имеет поле address, связанное с соответствующим объектом. Поскольку адрес у гражданина только один, то используется аннотация @ManyToOne. Аннотацией @JoinColumn определяется поле связи в таблице БД. Таким образом, параметры этих аннотаций несут такую же смысловую нагрузку, что и у связи @OneToOne.

А вот у владеемого объекта на этот раз всё иначе. Поскольку по одному адресу может проживать несколько жильцов, то поле tenants представлено коллекцией, которая имеет аннотацию @OneToMany. Параметр mappedBy также указывает на поле в классе владельца. Параметр fetch=FetchType.EAGER говорит о том, что при загрузке владеемого объекта необходимо сразу загрузить и коллекцию владельцев.

Читайте также:  пяточная шпора в каком возрасте может быть

Для чтения связанных объектов из БД используются следующие стратегии загрузок (fetch) : EAGER и LAZY. В первом случае объекты коллекции сразу загружаются в память, во втором случае — только при обращении к ним. Оба этих подхода имеют достоинства и недостатки.

В случае FetchType.EAGER в памяти будут находиться все загруженные объекты, даже если нужен только один объект из десятка (сотен/тысяч). При использовании данной стратегии необходимо быть внимательным, поскольку при загрузке какого-нибудь корневого объекта, который связан со всеми остальными объектами и коллекциями, можно случайно попытаться загрузить в память и всю базу.

Согласно стратегии FetchType.LAZY связанные объекты загружаются только по мере необходимости, т.е. при обращении. Но при этом требуется, чтобы соединение с базой (или транзакция) сохранялись. Если быть точно, то требуется, чтобы объект был attached. Поэтому для работы с lazy объектами тратится больше ресурсов на поддержку соединений.

@ManyToMany

Примером ассоциации @ManyToMany (многие-ко-многим) могут быть отношения студентов и ВУЗов. В одном институте может быть много студентов, студент может учиться в нескольких ВУЗах. Рассмотрим с начала таблицы БД :

Для определения связи @ManyToMany в примере потребуется три таблицы : таблица студентов students, таблица ВУЗов university и таблица связей student_university, в которой будут связаны студенты и ВУЗы. Кроме этого в таблице student_university определены внешние ключи (FOREIGN KEY), предупреждающие появление непрошенных записей при отсутствии родительских.

Теперь можно представить описание сущностей :

Список институтов в сущности Student аннотирован с помощью @ManyToMany. Далее следует аннотация @JoinTable, которая определяет таблицу и поля для связи. Параметр name указывает название таблицы (student_university). Параметр joinColumns указывает на поле, которое используется для прямой связи (идентификатор student_id). Параметр inverseJoinColumns указывает на поле, которое используется для обратной связи (идентификатор university_id). Для указания столбцов связи из таблицы используется аннотация @JoinColumn.

Сущность университета University описана «зеркально».

Пример связанных сущностей

Рассмотрим пример использования аннотаций @OneToMane и @ManyToOne при определении связанных сущностей. В качестве первой сущности будет использоваться пользователь User. Второй сущностью будет автомобиль Auto. Пользователь может владеть несколькими автомобилями, поэтому сущность User будет связана с Auto связью @OneToMany (один-ко-многим). Сущность Auto будет связана с сущностью User связью @ManyToOne (многие-к-одному). Начнем с объектов базы данных :

SQL-скрипты создания таблиц пользователей и автомобилей

Записи таблицы пользователей ничего не знают о записях таблицы автомобилей. А записи таблицы Autos связаны с таблицей Users по внешнему ключу (поле user_id). Синтаксис описания внешних ключей в базах данных представлен здесь.

SQL-скрипт создания Sequence

Генератор последовательностей SEQ_USER используем для определении идентификаторов записей сущностей. Как работать с генераторами последовательностей Sequence в SQL подробно представлено здесь.

Проект тестирования связанных сущностей Hibernate

На следующем скриншоте представлена структура проекта hibernate-entities в среде разработки Eclipse. В проекте необходимо определить файл конфигурации hibernate.cfg.xml и классы-сущности (User и Auto). Модуль HibernateExample будет тестировать настройки hibernate и сущностей. Все библиотеки, необходимые для работы с Oracle и hibernate, размещены в поддиректории lib. После включения их в CLASSPATH они отображаются в корне проекта Eclipse.

Примечание : в демонстрационном примере hibernate был использован «файл-маппинг» person.cfg.xml сущности Person. В данном примере вместо «файл-маппингов» будем использовать аннотации Подробная информация об аннотациях JPA представлена здесь.

Конфигурация hibernate

В конфигурационном XML-файле hibernate.cfg.xml определяем сервер БД (драйвер, пул подключений, диалект, кодировку) и параметры подключения (url, login, password), а также дополнительные параметры, которые будут использованы при работе с сервером. В качестве сервера БД выбран Oracle c пулом подключений в одно соединение. В демонстрационном примере в качестве сервера БД использовался MySQL.

Дополнительно определяем истиное значение свойства «show_sql» для отображения в консоли SQL-скриптов, генерируемых библиотекой Hibernate. В заключении в обязательном порядке определяем маппинг сущностей/классов User и Auto, чтобы не вызывать исключений.

Листинг класса пользователя User

Описание сущности/класса User незначительно изменилось. Добавилось поле List autos, определяющее список автомобилей пользователя.

Описание аннотаций @Table, @Id, @Column, @GeneratedValue, @SequenceGenerator сущности User представлено в предыдущей статье. Здесь дополним список описанием аннотации
@OneToMany
Атрибут fetch в аннотации, определяющий стратегию загрузки дочерних объектов, может принимать одно из двух значений перечисления javax.persistence.FetchType :

Атрибут cascade обозначает, какие из методов интерфейса Session будут распространяться каскадно к ассоциированным сущностям. Возможные варианты : CascadeType.ALL, CascadeType.PERSIST, CascadeType.MERGE. Необходимо правильно настроить CascadeType, чтобы не подгружать из базы данных лишних ассоциированных объектов-сущностей.

Листинг класса автомобиля Auto

При описании поля user используется аннотация @ManyToOne. Аннотация @JoinColumn определяет поле таблицы БД, по которому сущность Auto связана с пользователем User.

Листинг класса тестирования HibernateExample

HibernateExample используется для тестирования связей между сущностями Hibernate. Сначала создается сессия в методе createHibernateSession. При создании session устанавливается соединение с БД Oracle. Если сессия создана успешо, то в методе saveUser создаются два объекта (user1, user2), открывается транзакция и объекты сохраняются в БД. Для сохранения объектов используются методы save класса Session. После этого создаются два объекта типа Auto, у которых полям user присваивается значение первого пользователя. Объекты автомобилей сохраняются в БД и транзакция завершается.

Читайте также:  с какими трудностями сталкивается молодой учитель

После сохранения объектов в БД, пользователь user1 обновляется с использованием метода refresh() объекта сессии. Описание методов Session представлено здесь.

Выполнение примера

При выполнении примера в консоль выводится информация, представленная ниже. Поскольку установлен соответствующий флаг в файле конфигурации hibernate.cfg.xml, то формируемые библиотекой Hibernate SQL-скрипты также отображаются в консоли.

Информация, выведенная Hibernate в консоль, показывает, что сначала формируются SQL-скрипты (запросы к Sequence) для получения идентификаторов объектов пользователя и автомобиля, после этого создаются SQL-скрипты добавления пользователей и автомобилей в БД. И в заключение Hibernate создает SQL-скрипт select с использованием left outer join для обновления объектов.

«Распечатка» описаний пользователей показывет, что первый user имеет автомобили, второй — нет. Как Hibernate с использованием Sequence определяет значения идентификаторов подробно представлено в предыдущей статье.

В продолжении статьи рассмотрен вопрос чтения объектов с фильтрацией и без фильтрации.

Удаление связанных сущностей

Наличие или отсутствие связанной сущности в базе данных определяет способ удаления. Если связанная сущность отсутствует, то можно использовать оператор DELETE в HQL-запросе объекта Query. Но если сущность содержит связанный объект в таблице БД, то при выполнении транзакции удаления с использованием объекта Query будет вызвано соответствующее исключение. Удаление связанных сущностей необходимо выполнять с использованием объекта сессии Session. Подробнее об этом представлено при описании оператора DELETE в HQL-запросе.

Источник

Односторонние и двусторонние отношения в Hibernate

Всем нам хорошо известен ответ на вопрос, какими могут быть отношения между сущностями в Hibernate и JPA. Вариантов всего четыре:

Для каждого из отношений есть своя аннотация и, казалось бы, на этом можно закончить разговор, но все не так просто. Да и вообще, может ли быть что-то просто в Hibernate 😉 Каждое из выше перечисленных отношений может быть односторонним (unidirectional) или двусторонним (bidirectional), и если не принимать это во внимание, то можно столкнуться с массой проблем и странностей.

Для примера возьмем две простейшие сущности: пользователь и контакт. Очевидно, что каждый контакт связан с пользователем отношением многие к одному, а пользователь с контактами отношением один ко многим.

Односторонние отношения

Односторонним называется отношение, владельцем которого является только одна из двух сторон. Отсюда и название. Следует заметить, что при этом вторая сторона об этом отношении ничего не знает. Hibernate будет считать владельцем отношения ту сущность, в которой будет поставлена аннотация отношения.

Давайте попробуем сделать владельцем отношения сторону контакта. При этом сущности будут выглядеть следующим образом.

Если запустить этот код, то Hibernate создаст следующую структуру таблиц, которая выглядит для нас вполне привычно. Отношение между таблицами создается при помощи ссылочного поля user_id в таблице contacts.

Но выбор сущности Contact в качестве стороны владельца отношений в данном случае не очень удачен. Очевидно, что нам чаще нужна информация обо всех контактах пользователя чем о том, какому пользователю принадлежит контакт. Попробуем сделать владельцем контакта сущность пользователя. Для этого убираем поле user из класса Contact и добавляем поле со списком контактов в класс User. Получаем следующий код.

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

Чтобы связать сущности Hibernate создал дополнительную таблицу связи (join table) с именем users_contacts, хотя сущности вполне можно было бы связать через ссылочное поле в таблице contacts, как в предыдущем случае. Честно говоря, я не совсем понимаю, почему Hibernate поступает именно так. Буду рад, если кто-то поможет с этим разобраться в комментариях к статье.

Проблему можно легко решить добавив аннотацию JoinColumn к полю contacts.

При таких настройках связь будет проводиться при помощи колонки user_id в таблице contacts, а таблица связи создаваться не будет.

Двусторонние отношения

Запускаем код и смотрим на структуру таблиц. Помимо таблиц для пользователей и ролей Hibernate создаст две таблицы связи, хотя нам хватило бы и одной.

Дело в том, что вместо одного двустороннего отношения мы с вами сейчас создали два односторонних. Тоже самое произойдет и для отношения один ко многим. Чтобы Hibernate понял, что мы хотим создать именно двустороннее отношение нам нужно указать, какая из сторон является владельцем отношений, а какая является обратной стороной. Это делается при помощи атрибута mappedBy. Важно отметить, что указывается этот атрибут в аннотации, которая находится на противоположной стороне отношения.

Для отношения многие ко многим любая из сторон может быть владельцем. В случае с ролями и пользователями выберем сущность пользователя в качестве владельца. Для этого изменим описание поля users в классе Role следующим образом.

Теперь Hibernate создаст только одну таблицу связи users_roles.

Для такого кода Hibernate создаст привычную нам структуру из двух таблиц со ссылкой на пользователя в таблице контактов.

На этом все на этот раз! Благодарю, что дочитали до конца и надеюсь, что статья была полезной! Разумеется, очень жду от вас обратную связь в виде голосов и комментариев!

Источник

В чем разница между @JoinColumn и mappedBy при использовании ассоциации JPA @OneToMany

в чем разница между:

5 ответов

аннотации @JoinColumn указывает, что этот объект является владелец отношения (то есть: соответствующая таблица имеет столбец с внешним ключом к таблице, на которую ссылаются), а атрибут mappedBy указывает, что сущность на этой стороне является обратной связью, а владелец находится в» другой » сущности. Это также означает, что вы можете получить доступ к другой таблице из класса, который вы аннотировали с помощью » mappedBy «(полностью двунаправленный отношение.)

Читайте также:  пришла какая то социальная выплата 3000 что это

в частности, для кода в вопросе правильные аннотации будут выглядеть так:

@JoinColumn может использоваться с обеих сторон отношений. вопрос был об использовании @JoinColumn на @OneToMany стороны (редкий случай). И дело здесь в физическое дублирование информации (имя столбца) вместе с не оптимизирован SQL-запрос, который будет производить некоторые дополнительные операторы обновления.

С «многие к одному» являются (почти) всегда собственником части двунаправленного отношения в спецификации JPA, один ко многим ассоциации аннотируется @OneToMany (mappedBy=. )

войско имеет двунаправленное одно ко многим отношениям с солдатом через свойство войск. Вам не нужно (не должно) определять какое-либо физическое отображение на стороне mappedBy.

чтобы сопоставить двунаправленный один со многими, с one-to-many сторона как владеющая сторона, вы должны удалить mappedBy элемент и установите для многих значение один @JoinColumn как вставляемое и обновляемое значение false. Это решение не оптимизировано и создаст некоторые дополнительные инструкции UPDATE.

аннотации mappedBy в идеале всегда следует использовать родительскую сторону (класс компании) двунаправленного отношения, в этом случае он должен быть в классе компании, указывающем на переменную-член «компания» дочернего класса (Класс филиала)

аннотации @JoinColumn используется для указания сопоставленного столбца для присоединения к ассоциации сущностей, эта аннотация может использоваться в любом классе (Родительском или дочернем), но в идеале она должна использоваться только в одна сторона (либо в родительском классе, либо в дочернем классе не в обоих) здесь, в этом случае я использовал ее в дочерней стороне (класс ветви) двунаправленного отношения, указывающего внешний ключ в классе ветви.

ниже приведен рабочий пример :

дочерний класс, филиал

Я просто хотел бы добавить, что @JoinColumn не всегда должен быть связан с данные о физическом местоположении as этой ответ напрашивается. Вы можете объединить @JoinColumn с @OneToMany даже если в родительской таблице нет данных таблицы, указывающих на дочернюю таблицу.

вроде бы только в JPA 2.x+ хотя. Это полезно для ситуаций, когда вы хотите, чтобы дочерний класс просто содержал идентификатор родителя, а не полную ссылку.

если вы используете @OneToMany с mappedBy набор атрибутов, у вас есть двунаправленная Ассоциация, то есть вам нужно иметь @ManyToOne ассоциация на стороне ребенка, которая mappedBy ссылки.

Источник

Может кто-нибудь объяснить mappedBy в JPA и Hibernate?

Я новичок в спящем состоянии, и мне нужно использовать отношения один-ко-многим и многие-к-одному. Это двунаправленные отношения в моих объектах, так что я могу перемещаться в любом направлении. mappedBy это рекомендуемый способ, но я не мог этого понять. Может кто-нибудь объяснить:

Ради моего примера, вот мои занятия с аннотациями:

Авиакомпания :

AirlineFlights:

РЕДАКТИРОВАТЬ:

У AirlineFlights есть idAirline как ForeignKey, а у Airline нет idAirlineFlights. Это делает AirlineFlights в качестве владельца / идентифицирующего лица?

Теоретически, я бы хотел, чтобы авиакомпания стала владельцем авиакомпании.

Это говорит Hibernate: «Иди, посмотри на свойство bean, называемое« авиакомпания », на предмет, который у меня есть, чтобы найти конфигурацию».

MappedBy сигнализирует, что ключ для отношений находится на другой стороне.

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

Если вы этого не сделаете, Hibernate отобразит эти два отношения, поскольку это не то же самое отношение

поэтому мы должны сказать hibernate сделать отображение только в одну сторону и координировать их.

mappedby = «объект сущности того же класса, созданный в другом классе»

Например, Если мы применим отображение в классе Employee к объекту employee, внешний ключ из таблицы Employee будет удален.

Отношение таблицы против отношения сущности

В системе реляционных баз данных связь между one-to-many таблицами выглядит следующим образом:

Обратите внимание, что связь основана на столбце внешнего ключа (например, post_id ) в дочерней таблице.

Таким образом, существует единый источник правды, когда речь идет об управлении one-to-many отношениями за столом.

Теперь, если вы берете двунаправленное отношение сущности, которое отображается в one-to-many отношении таблицы, которое мы видели ранее:

Если вы посмотрите на диаграмму выше, вы увидите, что есть два способа управления этими отношениями.

В Post сущности у вас есть comments коллекция:

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

MappedBy

Синхронизировать обе стороны двунаправленной ассоциации

Теперь, даже если вы определили mappedBy атрибут и дочерняя сторона @ManyToOne управляет столбцом внешнего ключа, вам все равно нужно синхронизировать обе стороны двунаправленной ассоциации.

Вы начали с сопоставления ManyToOne, а затем добавили сопоставление OneToMany для двунаправленного способа. Затем на стороне OneToMany (обычно это ваша родительская таблица / класс), вы должны упомянуть «mappedBy» (отображение выполняется и в дочерней таблице / классе), поэтому hibernate не будет создавать таблицу отображения EXTRA в БД (как TableName = parent_child).

Источник

Сказочный портал