@ManyToAny в Hibernate
Аннотация @ManyToAny позволяет реализовать полиморфную ассоциацию, где сущность может ссылаться на разные типы других сущностей через единое поле. Это аналог @ManyToMany, но без жесткой привязки к конкретному классу.
Пакет: org.hibernate.annotations
Применяется к: полям типа List, Set или Map.
Требует:
@AnyMetaDef (определяет маппинг типов).
@JoinTable или @CollectionTable (если ассоциация хранится в отдельной таблице).
Параметры и настройки
Обязательные аннотации
@AnyMetaDef
Определяет, как Hibernate будет различать типы сущностей.
Атрибуты:
name (String): уникальное имя (используется в @ManyToAny).
metaType (String): тип дискриминатора (обычно "string" или "integer").
idType (String): тип ID (например, "long").
metaValues (массив @MetaValue): связывает значения с классами.
@ManyToAny
Атрибуты:
metaDef (String): имя @AnyMetaDef.
fetch (FetchType): LAZY (по умолчанию) или EAGER.
Жизненный цикл и обработка
Как хранится связь?
Для @ManyToAny требуется отдельная таблица (аналог @ManyToMany), которая содержит:
ID владельца (сущности, где объявлено @ManyToAny).
ID целевой сущности.
Дискриминатор (тип сущности из @MetaValue).
Загрузка данных
При обращении к полю Hibernate:
Смотрит item_type и item_id.
Определяет класс через @AnyMetaDef.
Загружает сущность (Book или Movie).
Примеры использования
Пример 1: Полиморфная коллекция
Пример 2: Ссылка на одну сущность
Проблемы
Нет типобезопасности: коллекция содержит Object, требуется проверка instanceof.
Сложные запросы: JPA/HQL не поддерживают полиморфные ассоциации в WHERE.
Нет каскадирования: нельзя использовать CascadeType.ALL.
#Java #Training #Hard #Spring #Hibernate #ManyToAny
Аннотация @ManyToAny позволяет реализовать полиморфную ассоциацию, где сущность может ссылаться на разные типы других сущностей через единое поле. Это аналог @ManyToMany, но без жесткой привязки к конкретному классу.
Пакет: org.hibernate.annotations
Применяется к: полям типа List, Set или Map.
Требует:
@AnyMetaDef (определяет маппинг типов).
@JoinTable или @CollectionTable (если ассоциация хранится в отдельной таблице).
Параметры и настройки
Обязательные аннотации
@AnyMetaDef
Определяет, как Hibernate будет различать типы сущностей.
Атрибуты:
name (String): уникальное имя (используется в @ManyToAny).
metaType (String): тип дискриминатора (обычно "string" или "integer").
idType (String): тип ID (например, "long").
metaValues (массив @MetaValue): связывает значения с классами.
@AnyMetaDef(
name = "myMetaDef",
metaType = "string",
idType = "long",
metaValues = {
@MetaValue(targetEntity = Book.class, value = "BOOK"),
@MetaValue(targetEntity = Movie.class, value = "MOVIE")
}
)
@ManyToAny
Атрибуты:
metaDef (String): имя @AnyMetaDef.
fetch (FetchType): LAZY (по умолчанию) или EAGER.
Жизненный цикл и обработка
Как хранится связь?
Для @ManyToAny требуется отдельная таблица (аналог @ManyToMany), которая содержит:
ID владельца (сущности, где объявлено @ManyToAny).
ID целевой сущности.
Дискриминатор (тип сущности из @MetaValue).
Загрузка данных
При обращении к полю Hibernate:
Смотрит item_type и item_id.
Определяет класс через @AnyMetaDef.
Загружает сущность (Book или Movie).
Примеры использования
Пример 1: Полиморфная коллекция
@Entity
public class User {
@Id
private Long id;
@ManyToAny
@AnyMetaDef(
name = "itemMetaDef",
metaType = "string",
idType = "long",
metaValues = {
@MetaValue(targetEntity = Book.class, value = "BOOK"),
@MetaValue(targetEntity = Movie.class, value = "MOVIE")
}
)
@JoinTable(
name = "user_items",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "item_id")
)
@Column(name = "item_type") // Дискриминатор
private List<Object> items; // Может содержать Book и Movie
}
Пример 2: Ссылка на одну сущность
@Entity
public class Review {
@Id
private Long id;
@Any(metaDef = "contentMetaDef", metaColumn = @Column(name = "content_type"))
@JoinColumn(name = "content_id")
private Object content; // Может быть Book или Movie
}
Проблемы
Нет типобезопасности: коллекция содержит Object, требуется проверка instanceof.
Сложные запросы: JPA/HQL не поддерживают полиморфные ассоциации в WHERE.
Нет каскадирования: нельзя использовать CascadeType.ALL.
#Java #Training #Hard #Spring #Hibernate #ManyToAny