Подтвердить что ты не робот

Как использовать Hibernate @Любые связанные аннотации?

Может ли кто-нибудь объяснить мне, как аннотации Any-related (@Any, @AnyMetaDef, @AnyMetaDefs и @ManyToAny) работают на практике. Мне трудно найти полезную документацию (только JavaDoc не очень помогает).

Я до сих пор собрался, что они каким-то образом позволяют ссылаться на абстрактные и расширенные классы. Если это так, почему нет аннотации @OneToAny? И этот "любой" относится к одному "любому" или нескольким "любым"?

Короткий, практичный и иллюстрирующий пример был бы очень оценен (его не нужно компилировать).

Изменить: столько, сколько я хотел бы принимать ответы в качестве ответов и отдать должное должным образом, я нашел ответы на вопросы как Smink, так и Sakana информативными. Поскольку я не могу принять несколько ответов в качестве ответа, я, к сожалению, не буду отмечать ни как ответ.

4b9b3361

Ответ 1

Надеемся, что эта статья освещает тему:

Иногда нам нужно сопоставить свойство ассоциации для разных типы объектов, которые не имеют общий объект предка - так просто полиморфная ассоциация не выполняет работа.

Например, допустим три разных приложения, которые управляют медиабиблиотекой - первое приложение управляет заимствованием книг, вторым DVD-дисками и третьими VHS. Приложения не имеют ничего общего. Теперь мы хотим разработать новое приложение, которое управляет всеми тремя типами носителей и повторно использует существующие объекты Book, DVD и VHS. Поскольку классы книг, DVD и VHS поступали из разных приложений, у них нет сущности-предка - общим предком является java.lang.Object. Тем не менее мы хотели бы иметь один объект Borrow, который может ссылаться на любой из возможных типов медиа.

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

@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;
    }

}

Ответ 2

Аннотация @Any определяет полиморфную связь с классами из нескольких таблиц. Этот тип отображения всегда требуется более одного столбца. Первый столбец содержит тип связанного объекта. Оставшиеся столбцы содержат идентификатор. Невозможно указать ограничение внешнего ключа для такого рода ассоциаций, поэтому это, безусловно, не означает, как обычный способ сопоставления (полиморфных) ассоциаций. Вы должны использовать это только в особых случаях (например, журналы аудита, данные сеанса пользователя и т.д.). Аннотация @Any описывает столбец, содержащий информацию метаданных. Чтобы связать значение метаданных и фактического типа сущности, используются аннотации @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 позволяет использовать полиморфные ассоциации для классов из нескольких таблиц. Этот тип отображения всегда требует более одного столбца. Первый столбец содержит тип связанного объекта. Остальные столбцы удерживайте идентификатор. Невозможно указать ограничение внешнего ключа для такого рода связей, так что это больше всего конечно, не означает как обычный способ сопоставления (полиморфных) ассоциаций. Вы должны использовать это только в очень специальные случаи (например, журналы аудита, данные сеанса пользователя и т.д.).

@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<Property> getGeneralProperties() {

Src: Справочное руководство по Hibernate Annotations 3.4.0GA

Надеюсь, что это поможет!

Ответ 3

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

Ответ 4

Аннота @Any определяет полиморфную связь с классами из нескольких таблиц, но полиморфные ассоциации, такие как анти-шаблон SQL! Основная причина заключается в том, что вы не можете определить ограничение FK, если столбец может ссылаться на более чем одну таблицу.

Одно из решений, упомянутое Биллом Карвином в его книге, заключается в создании таблиц пересечений для каждого типа "Любой", вместо использования одного столбца с "типом" и использования уникального модификатора, чтобы избежать дублирования. Это решение может быть болью для работы с JPA.

Другое решение, также предложенное Karwin, заключается в создании супертипа для связанных элементов. Взяв пример заимствования книги, DVD или VHS, вы можете создать супертипный элемент и сделать наследование книг, DVD и VHS с помощью Item со стратегией "Присоединиться к таблице". Затем заимствуйте очки на предмет. Таким образом, вы полностью избегаете проблемы 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
}