@MetaValue в Hibernate
Аннотация @MetaValue используется в связке с @AnyMetaDef, @ManyToAny или @Any для определения соответствия между дискриминатором (меткой типа) и конкретным классом сущности. Она позволяет Hibernate понять, какую сущность загружать при полиморфных ассоциациях.
Пакет: org.hibernate.annotations
Применяется внутри: @AnyMetaDef.metaValues или @TypeDef.metaValues.
Параметры и настройки
Атрибуты @MetaValue
targetEntity: Класс сущности, на который ссылается метка.
value: Значение дискриминатора в БД (например, "BOOK" или 1).
Пример использования
Жизненный цикл и обработка
Как работает @MetaValue?
При сохранении:
Hibernate смотрит тип объекта в коллекции (например, Book).
Записывает в столбец-дискриминатор (item_type) значение "BOOK".
При загрузке:
Hibernate читает item_type из БД (например, "MOVIE").
Сопоставляет значение с классом Movie через @MetaValue.
Загружает сущность Movie по item_id.
Где хранится дискриминатор?
В отдельном столбце таблицы (например, item_type).
Или в общей таблице, если используется @Any + @Column.
Примеры использования
Пример 1: Полиморфная коллекция (@ManyToAny)
Пример 2: Одиночная полиморфная ссылка (@Any)
Ограничения
Нет типобезопасности:
Коллекция List<Object> требует проверки instanceof.
Решение: использовать Visitor-паттерн или DTO.
Ограниченная поддержка в JPA:
Запросы с WHERE content_type = 'BOOK' не работают в чистом JPA.
Решение: нативные SQL-запросы или Hibernate.initialize().
Нет каскадирования:
CascadeType.ALL не поддерживается.
#Java #Training #Hard #Spring #Hibernate #MetaValue
Аннотация @MetaValue используется в связке с @AnyMetaDef, @ManyToAny или @Any для определения соответствия между дискриминатором (меткой типа) и конкретным классом сущности. Она позволяет Hibernate понять, какую сущность загружать при полиморфных ассоциациях.
Пакет: org.hibernate.annotations
Применяется внутри: @AnyMetaDef.metaValues или @TypeDef.metaValues.
Параметры и настройки
Атрибуты @MetaValue
targetEntity: Класс сущности, на который ссылается метка.
value: Значение дискриминатора в БД (например, "BOOK" или 1).
Пример использования
@AnyMetaDef(
name = "mediaMetaDef",
metaType = "string", // Тип столбца-дискриминатора (varchar)
idType = "long", // Тип ID целевой сущности
metaValues = {
@MetaValue(targetEntity = Book.class, value = "BOOK"),
@MetaValue(targetEntity = Movie.class, value = "MOVIE")
}
)
Жизненный цикл и обработка
Как работает @MetaValue?
При сохранении:
Hibernate смотрит тип объекта в коллекции (например, Book).
Записывает в столбец-дискриминатор (item_type) значение "BOOK".
При загрузке:
Hibernate читает item_type из БД (например, "MOVIE").
Сопоставляет значение с классом Movie через @MetaValue.
Загружает сущность Movie по item_id.
Где хранится дискриминатор?
В отдельном столбце таблицы (например, item_type).
Или в общей таблице, если используется @Any + @Column.
Примеры использования
Пример 1: Полиморфная коллекция (@ManyToAny)
@Entity
public class Library {
@Id
private Long id;
@ManyToAny
@AnyMetaDef(
name = "mediaMetaDef",
metaType = "string",
idType = "long",
metaValues = {
@MetaValue(targetEntity = Book.class, value = "BOOK"),
@MetaValue(targetEntity = Movie.class, value = "MOVIE")
}
)
@JoinTable(
name = "library_items",
joinColumns = @JoinColumn(name = "library_id"),
inverseJoinColumns = @JoinColumn(name = "item_id")
)
@Column(name = "item_type") // Столбец для дискриминатора
private List<Object> items; // Может содержать Book и Movie
}
Пример 2: Одиночная полиморфная ссылка (@Any)
@Entity
public class Review {
@Id
private Long id;
@Any(metaDef = "mediaMetaDef")
@JoinColumn(name = "content_id")
@Column(name = "content_type") // Дискриминатор
private Object content; // Book или Movie
}
Ограничения
Нет типобезопасности:
Коллекция List<Object> требует проверки instanceof.
Решение: использовать Visitor-паттерн или DTO.
Ограниченная поддержка в JPA:
Запросы с WHERE content_type = 'BOOK' не работают в чистом JPA.
Решение: нативные SQL-запросы или Hibernate.initialize().
Нет каскадирования:
CascadeType.ALL не поддерживается.
#Java #Training #Hard #Spring #Hibernate #MetaValue