Как использовать Hibernate @ Любые связанные annotations?
Может ли кто-нибудь объяснить мне, как annotations Any-related ( @Any
, @AnyMetaDef
, @AnyMetaDefs
и @ManyToAny
) работают на практике. Мне сложно найти любую полезную документацию (только JavaDoc не очень помогает).
Я до сих пор собрался, что они каким-то образом позволяют ссылаться на абстрактные и расширенные classы. Если это так, почему нет annotations @OneToAny
? И этот «любой» относится к одному «любому» или нескольким «любым»?
Короткий, практичный и иллюстрирующий пример был бы очень оценен (его не нужно компилировать).
- Уникальные поля, допускающие нули в Django
- В чем разница между fetch = "EAGER" и fetch = "LAZY" в доктрине
- Что называется ссылочным именем ColumnName, используемым в JPA?
- Hibernate Annotations - Что лучше, поле или доступ к собственности?
- Бесконечная recursion с выпуском Jackson JSON и Hibernate JPA
Изменить: насколько я хотел бы принимать ответы в качестве ответов и давать должное должное, я нашел ответы на вопросы Smink и Sakana информативными. Поскольку я не могу принять несколько ответов в качестве ответа , я, к сожалению, не буду отмечать ни как ответ.
- Что используется session.flush () в Hibernate
- Какой ORM я должен использовать для Node.js и MySQL?
- Как удалить объект с отношениями ManyToMany в JPA (и соответствующие строки таблицы соединений)?
- Почему вы должны использовать ORM?
- Ошибка: java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter. (I) V
- Каковы преимущества использования ORM?
- JPA - сохранение отношения от одного до большого
- Hibernate - @ElementCollection - странное поведение удаления / вставки
Надеюсь, что эта статья освещает тему:
Иногда нам нужно сопоставить свойство ассоциации с различными типами сущностей, у которых нет общего объекта-предка, поэтому простая полиморфная ассоциация не выполняет эту работу.
Например, допустим три разных приложения, которые управляют медиабиблиотекой – первое приложение управляет заимствованием книг, вторым DVD-дисками и третьими VHS. Приложения не имеют ничего общего. Теперь мы хотим разработать новое приложение, которое управляет всеми тремя типами носителей и повторно использует существующие объекты Book, DVD и VHS. Поскольку classы книг, DVD и VHS поступали из разных приложений, у них нет сущности-предка – общим предком является java.lang.Object. Тем не менее мы хотели бы иметь один объект Borrow, который может ссылаться на любой из возможных типов медиа.
Чтобы решить этот тип ссылок, мы можем использовать любое отображение. это сопоставление всегда включает более одного столбца: в один столбец входит тип объекта, к которому относится текущее сопоставленное свойство, а другое включает в себя идентификатор объекта, например, если мы ссылаемся на книгу, в первом столбце будет указан маркер для тип объекта Book, а второй – идентификатор конкретной книги.
@Entity @Table(name = "BORROW") public class Borrow{ @Id @GeneratedValue private Long id; @Any(metaColumn = @Column(name = "ITEM_TYPE")) @AnyMetaDef(idType = "long", metaType = "string", metaValues = { @MetaValue(targetEntity = Book.class, value = "B"), @MetaValue(targetEntity = VHS.class, value = "V"), @MetaValue(targetEntity = DVD.class, value = "D") }) @JoinColumn(name="ITEM_ID") private Object item; ....... public Object getItem() { return item; } public void setItem(Object item) { this.item = item; } }
Аннота @Any определяет полиморфную связь с classами из нескольких таблиц. Для такого типа отображения всегда требуется более одного столбца. Первый столбец содержит тип связанного объекта. Остальные столбцы содержат идентификатор. Невозможно указать ограничение внешнего ключа для такого рода ассоциаций, поэтому это, безусловно, не означает обычный способ сопоставления (полиморфных) ассоциаций. Вы должны использовать это только в особых случаях (например, журналы аудита, данные сеанса пользователя и т. Д.). Аннотация @Any описывает столбец, содержащий информацию метаданных. Чтобы связать значение информации метаданных и фактического типа объекта, используются annotations @AnyDef и @AnyDefs.
@Any( metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER ) @AnyMetaDef( idType = "integer", metaType = "string", metaValues = { @MetaValue( value = "S", targetEntity = StringProperty.class ), @MetaValue( value = "I", targetEntity = IntegerProperty.class ) } ) @JoinColumn( name = "property_id" ) public Property getMainProperty() { return mainProperty; }
idType представляет тип свойства идентификатора целевых объектов и metaType тип метаданных (обычно String). Обратите внимание, что @AnyDef может быть взаимозависимым и повторно использоваться. В этом случае рекомендуется поместить его в виде метаданных пакета.
//on a package @AnyMetaDef( name="property" idType = "integer", metaType = "string", metaValues = { @MetaValue( value = "S", targetEntity = StringProperty.class ), @MetaValue( value = "I", targetEntity = IntegerProperty.class ) } ) package org.hibernate.test.annotations.any; //in a class @Any( metaDef="property", metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER ) @JoinColumn( name = "property_id" ) public Property getMainProperty() { return mainProperty; }
@ManyToAny позволяет использовать полиморфные ассоциации для classов из нескольких таблиц. Для такого типа отображения всегда требуется более одного столбца. Первый столбец содержит тип связанного объекта. Остальные столбцы содержат идентификатор. Невозможно указать ограничение внешнего ключа для такого рода ассоциаций, поэтому это, безусловно, не означает обычный способ сопоставления (полиморфных) ассоциаций. Вы должны использовать это только в особых случаях (например, журналы аудита, данные сеанса пользователя и т. Д.).
@ManyToAny( metaColumn = @Column( name = "property_type" ) ) @AnyMetaDef( idType = "integer", metaType = "string", metaValues = { @MetaValue( value = "S", targetEntity = StringProperty.class ), @MetaValue( value = "I", targetEntity = IntegerProperty.class ) } ) @Cascade( { org.hibernate.annotations.CascadeType.ALL } ) @JoinTable( name = "obj_properties", joinColumns = @JoinColumn( name = "obj_id" ), inverseJoinColumns = @JoinColumn( name = "property_id" ) ) public List getGeneralProperties() {
Src: Hibernate Annotations Справочное руководство 3.4.0GA
Надеюсь, поможет!
Вы читали документацию по Hibernate Annotations для @ Any ? Раньше я еще не использовал это, но он выглядит как расширенный способ определения ссылок. Ссылка включает пример, хотя я не знаю, достаточно ли этого, чтобы полностью понять концепцию …
Аннота @Any определяет полиморфную связь с classами из нескольких таблиц, но полиморфные ассоциации, такие как анти-шаблон SQL! Основная причина заключается в том, что вы не можете определить ограничение FK, если столбец может ссылаться на более чем одну таблицу.
Одним из решений, на которое указывает Билл Карвин в своей книге, является создание таблиц пересечений для каждого типа «Любой», вместо использования одного столбца с «типом» и использования уникального модификатора, чтобы избежать дублирования. Это решение может быть больно работать с JPA.
Другое решение, также предложенное Карвином, заключается в создании супертипа для связанных элементов. Взяв пример заимствования книги, DVD или VHS, вы можете создать супертипный элемент и сделать наследование книг, DVD и VHS с помощью Item со страtagsей «Присоединиться к таблице». Затем заимствуйте очки на предмет. Таким образом, вы полностью избегаете проблемы FK. Я перевел пример книги на репортаж JPA:
@Entity @Table(name = "BORROW") public class Borrow{ //... id, ... @ManyToOne Item item; //... } @Entity @Table(name = "ITEMS") @Inheritance(strategy=JOINED) public class Item{ // id, .... // you can add a reverse OneToMany here to borrow. } @Entity @Table(name = "BOOKS") public class Book extends Item { // book attributes } @Entity @Table(name = "VHS") public class VHS extends Item { // VHSattributes } @Entity @Table(name = "DVD") public class DVD extends Item { // DVD attributes }