Вопросы с собеседования 👩💻
Что делает метод peek() в Queue?
Что делает метод peek() в Queue?
Anonymous Quiz
12%
Удаляет элемент
75%
Возвращает первый элемент без удаления
8%
Добавляет элемент
6%
Сортирует очередь
@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
@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
Что выведет код?
#Tasks
import java.util.HashMap;
import java.util.Map;
class Employee160425 {
String name;
Employee160425(String name) { this.name = name; }
@Override
public boolean equals(Object o) {
return this.name.equals(((Employee160425)o).name);
}
@Override
public int hashCode() {
return name.length();
}
}
public class Task160425 {
public static void main(String[] args) {
Map<Employee160425, String> map = new HashMap<>();
Employee160425 e1 = new Employee160425("John");
Employee160425 e2 = new Employee160425("Jane");
map.put(e1, "Developer");
map.put(e2, "Manager");
e1.name = "Johnny";
System.out.println(map.get(e1));
System.out.println(map.get(new Employee160425("John")));
}
}
#Tasks
Варианты ответа:
Anonymous Quiz
16%
Developer и Developer
34%
Developer и null
25%
null и null
25%
Exception какой-то
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩💻
Какой метод используется для получения значения из Optional?
Какой метод используется для получения значения из Optional?
Anonymous Quiz
31%
value()
10%
fetch()
55%
get()
5%
retrieve()
@NaturalId в Hibernate
Аннотация @NaturalId помечает естественный (бизнес-идентификатор) поля сущности, который не является техническим первичным ключом (@Id), но обладает уникальностью и часто используется для поиска.
Пакет: org.hibernate.annotations
Применяется к: полям или свойствам сущности (String, Integer, UUID и др.).
Особенности:
Ускоряет поиск по "естественному" ключу (Hibernate кеширует NaturalId → ID).
Может быть изменяемым (mutable) или неизменяемым (immutable).
Параметры и настройки
mutable: Если true — NaturalId можно изменить (по умолчанию false).
Примеры
Жизненный цикл и обработка
Как работает @NaturalId?
При сохранении:
Hibernate проверяет уникальность NaturalId (если нет @UniqueConstraint).
Добавляет запись в кеш NaturalId → ID.
При поиске:
session.bySimpleNaturalId(User.class).load("test@mail.com") — использует кеш.
Генерирует SQL: SELECT id FROM users WHERE email = ?.
При изменении (если mutable=true):
Обновляет кеш (старое значение удаляется, новое добавляется).
Кеширование
Уровень L1 (сессия): Кешируется в рамках текущей сессии.
Уровень L2 (глобальный): Требует включенного кеша второго уровня.
Примеры использования
Пример 1: Неизменяемый NaturalId
Пример 2: Поиск по NaturalId
Ограничения
Производительность при mutable=true:
Частые изменения NaturalId требуют обновления кеша.
Отсутствие JPA-стандарта:
@NaturalId — это фича Hibernate (не работает в EclipseLink).
Когда использовать?
Для часто используемых бизнес-идентификаторов (email, ISBN, серийные номера).
Вместо @Id, если первичный ключ — суррогатный (автоинкремент).
#Java #Training #Hard #Spring #Hibernate #NaturalId
Аннотация @NaturalId помечает естественный (бизнес-идентификатор) поля сущности, который не является техническим первичным ключом (@Id), но обладает уникальностью и часто используется для поиска.
Пакет: org.hibernate.annotations
Применяется к: полям или свойствам сущности (String, Integer, UUID и др.).
Особенности:
Ускоряет поиск по "естественному" ключу (Hibernate кеширует NaturalId → ID).
Может быть изменяемым (mutable) или неизменяемым (immutable).
Параметры и настройки
mutable: Если true — NaturalId можно изменить (по умолчанию false).
Примеры
@Entity
public class User {
@Id
private Long id;
@NaturalId(mutable = false) // Неизменяемый (оптимизирует кеширование)
private String email;
@NaturalId(mutable = true) // Изменяемый (редкий случай)
private String passportNumber;
}
Жизненный цикл и обработка
Как работает @NaturalId?
При сохранении:
Hibernate проверяет уникальность NaturalId (если нет @UniqueConstraint).
Добавляет запись в кеш NaturalId → ID.
При поиске:
session.bySimpleNaturalId(User.class).load("test@mail.com") — использует кеш.
Генерирует SQL: SELECT id FROM users WHERE email = ?.
При изменении (если mutable=true):
Обновляет кеш (старое значение удаляется, новое добавляется).
Кеширование
Уровень L1 (сессия): Кешируется в рамках текущей сессии.
Уровень L2 (глобальный): Требует включенного кеша второго уровня.
Примеры использования
Пример 1: Неизменяемый NaturalId
@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = "isbn"))
public class Book {
@Id
private Long id;
@NaturalId // immutable=false по умолчанию
private String isbn;
}
Пример 2: Поиск по NaturalId
Book book = session.bySimpleNaturalId(Book.class)
.load("978-3-16-148410-0");
Ограничения
Производительность при mutable=true:
Частые изменения NaturalId требуют обновления кеша.
Отсутствие JPA-стандарта:
@NaturalId — это фича Hibernate (не работает в EclipseLink).
Когда использовать?
Для часто используемых бизнес-идентификаторов (email, ISBN, серийные номера).
Вместо @Id, если первичный ключ — суррогатный (автоинкремент).
#Java #Training #Hard #Spring #Hibernate #NaturalId
@NotFound в Hibernate
Аннотация @NotFound управляет поведением Hibernate при отсутствии ссылки на связанную сущность в базе данных (например, если @ManyToOne ссылается на несуществующий ID).
Пакет: org.hibernate.annotations
Применяется к: ассоциациям (@OneToOne, @ManyToOne, @OneToMany, @ManyToMany).
Поведение по умолчанию: Hibernate выбрасывает EntityNotFoundException.
Параметры и настройки
action: Действие при отсутствии сущности: EXCEPTION (по умолчанию) или IGNORE.
Примеры
Жизненный цикл и обработка
Как работает @NotFound?
При загрузке сущности:
Если связанная сущность (например, User) не найдена:
action = EXCEPTION → EntityNotFoundException.
action = IGNORE → поле устанавливается в null.
При каскадных операциях:
Не влияет на CascadeType (удаление, обновление).
Сценарии
Ссылка на удаленную сущность:
Ленивая загрузка:
Если прокси не может загрузить сущность, применяется action.
Интеграция с Spring Boot
Валидация при старте:
Чтобы выявить "битые" ссылки заранее:
Логирование:
Примеры использования
Пример 1: Игнорирование отсутствующей сущности
Пример 2: Обработка в сервисе
Проблемы
Неявное поведение:
IGNORE может скрывать ошибки данных.
Нет поддержки в JPA:
Это фича Hibernate (не работает в EclipseLink).
Когда использовать?
Для опциональных ассоциаций, где null — допустимое состояние.
В legacy-системах с "битыми" ссылками.
#Java #Training #Hard #Spring #Hibernate #NotFound
Аннотация @NotFound управляет поведением Hibernate при отсутствии ссылки на связанную сущность в базе данных (например, если @ManyToOne ссылается на несуществующий ID).
Пакет: org.hibernate.annotations
Применяется к: ассоциациям (@OneToOne, @ManyToOne, @OneToMany, @ManyToMany).
Поведение по умолчанию: Hibernate выбрасывает EntityNotFoundException.
Параметры и настройки
action: Действие при отсутствии сущности: EXCEPTION (по умолчанию) или IGNORE.
Примеры
@Entity
public class Order {
@ManyToOne
@NotFound(action = NotFoundAction.IGNORE) // Игнорировать отсутствие пользователя
private User user;
}
Жизненный цикл и обработка
Как работает @NotFound?
При загрузке сущности:
Если связанная сущность (например, User) не найдена:
action = EXCEPTION → EntityNotFoundException.
action = IGNORE → поле устанавливается в null.
При каскадных операциях:
Не влияет на CascadeType (удаление, обновление).
Сценарии
Ссылка на удаленную сущность:
-- order.user_id = 999, но users.id = 999 не существует
@NotFound(action = IGNORE) → order.user = null.
Ленивая загрузка:
Если прокси не может загрузить сущность, применяется action.
Интеграция с Spring Boot
Валидация при старте:
Чтобы выявить "битые" ссылки заранее:
@EventListener(ApplicationReadyEvent.class)
public void checkBrokenReferences() {
// Ручная проверка...
}
Логирование:
logging.level.org.hibernate=DEBUG
Примеры использования
Пример 1: Игнорирование отсутствующей сущности
@Entity
public class Comment {
@ManyToOne
@NotFound(action = NotFoundAction.IGNORE)
private Post post; // Если post удалён, comment.post = null
}
Пример 2: Обработка в сервисе
public CommentDTO getComment(Long id) {
Comment comment = commentRepository.findById(id).orElseThrow();
if (comment.getPost() == null) {
log.warn("Пост для комментария {} не найден", id);
}
return toDto(comment);
}
Проблемы
Неявное поведение:
IGNORE может скрывать ошибки данных.
Нет поддержки в JPA:
Это фича Hibernate (не работает в EclipseLink).
Когда использовать?
Для опциональных ассоциаций, где null — допустимое состояние.
В legacy-системах с "битыми" ссылками.
#Java #Training #Hard #Spring #Hibernate #NotFound
Что выведет код?
#Tasks
import java.util.HashMap;
class Key170425 {
int id;
Key170425(int id) {
this.id = id;
}
@Override
public int hashCode() {
return id % 2;
}
@Override
public boolean equals(Object o) {
return this.id % 2 == ((Key170425)o).id % 2;
}
}
public class Task170425 {
public static void main(String[] args) {
HashMap<Key170425, String> map = new HashMap<>();
map.put(new Key170425(1), "Apple");
map.put(new Key170425(2), "Banana");
map.put(new Key170425(3), "Cherry");
System.out.println(map.size());
}
}
#Tasks
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩💻
Какой метод используется для округления числа вниз?
Какой метод используется для округления числа вниз?
Anonymous Quiz
56%
Math.floor()
20%
Math.ceil()
22%
Math.round()
2%
Math.trunc()
@OnDelete в Hibernate
Аннотация @OnDelete определяет действие при удалении связанной сущности на уровне базы данных (через ON DELETE CASCADE или ON DELETE SET NULL). Это DDL-инструкция, а не логика Hibernate.
Пакет: org.hibernate.annotations
Применяется к: ассоциациям (@OneToOne, @ManyToOne, @OneToMany).
Влияние: Генерирует соответствующий SQL-констрейнт в БД.
Параметры и настройки
action: Варианты: CASCADE (удалить зависимые записи) или SET_NULL (обнулить ссылку).
Примеры
Жизненный цикл и обработка
Как работает @OnDelete?
При генерации DDL:
Hibernate добавляет в SQL-скрипт ON DELETE CASCADE/SET NULL для внешнего ключа.
При удалении через БД:
Если запись удаляется напрямую SQL (минуя Hibernate), констрейнт срабатывает автоматически.
При удалении через Hibernate:
Если action = CASCADE, Hibernate сначала удаляет дочерние сущности (если нет orphanRemoval).
Ограничения
Не влияет на логику EntityManager.remove().
Не работает с @ManyToMany (только через @JoinTable + отдельные констрейнты).
Примеры использования
Пример 1: Каскадное удаление (CASCADE)
Пример 2: Обнуление ссылки (SET_NULL)
Проблемы
Неявное удаление: При CASCADE данные могут исчезнуть без явного вызова delete().
Несовместимость: Некоторые БД (например, MySQL с InnoDB) требуют индексов для ON DELETE CASCADE.
Когда использовать?
Для жестких зависимостей (например, Order → User).
В legacy-системах, где удаление управляется триггерами БД.
#Java #Training #Hard #Spring #Hibernate #OnDelete
Аннотация @OnDelete определяет действие при удалении связанной сущности на уровне базы данных (через ON DELETE CASCADE или ON DELETE SET NULL). Это DDL-инструкция, а не логика Hibernate.
Пакет: org.hibernate.annotations
Применяется к: ассоциациям (@OneToOne, @ManyToOne, @OneToMany).
Влияние: Генерирует соответствующий SQL-констрейнт в БД.
Параметры и настройки
action: Варианты: CASCADE (удалить зависимые записи) или SET_NULL (обнулить ссылку).
Примеры
@Entity
public class Order {
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE) // При удалении User удалятся его Order
private User user;
}
Жизненный цикл и обработка
Как работает @OnDelete?
При генерации DDL:
Hibernate добавляет в SQL-скрипт ON DELETE CASCADE/SET NULL для внешнего ключа.
При удалении через БД:
Если запись удаляется напрямую SQL (минуя Hibernate), констрейнт срабатывает автоматически.
При удалении через Hibernate:
Если action = CASCADE, Hibernate сначала удаляет дочерние сущности (если нет orphanRemoval).
Ограничения
Не влияет на логику EntityManager.remove().
Не работает с @ManyToMany (только через @JoinTable + отдельные констрейнты).
Примеры использования
Пример 1: Каскадное удаление (CASCADE)
@Entity
public class Comment {
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE) // Удалить комментарии при удалении Post
private Post post;
}
Пример 2: Обнуление ссылки (SET_NULL)
@Entity
public class Employee {
@ManyToOne
@OnDelete(action = OnDeleteAction.SET_NULL) // department_id = NULL при удалении Department
private Department department;
}
Проблемы
Неявное удаление: При CASCADE данные могут исчезнуть без явного вызова delete().
Несовместимость: Некоторые БД (например, MySQL с InnoDB) требуют индексов для ON DELETE CASCADE.
Когда использовать?
Для жестких зависимостей (например, Order → User).
В legacy-системах, где удаление управляется триггерами БД.
#Java #Training #Hard #Spring #Hibernate #OnDelete