Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Пишем тестовое задание от реального работодателя для новичков! Часть 2 (начало).
Встреча от 13.04.25
Запись встречи -
YOUTUBE
RUTUBE
На сегодняшней встрече наш подписчик @Shikin_Anatoliy рискнул продолжить писать тестовое задание от реального работодателя.
Что мы успели в рамках второй серии:
- Доработали Player
- Создали CRUD для Team
- Все простестили и проработали
Допустили и решили пару систематических ошибок, повторили основы написания.
Ждите продолжения!
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
@Shikin_Anatoliy - респект и уважуха💪
Встреча от 13.04.25
Запись встречи -
YOUTUBE
RUTUBE
На сегодняшней встрече наш подписчик @Shikin_Anatoliy рискнул продолжить писать тестовое задание от реального работодателя.
Что мы успели в рамках второй серии:
- Доработали Player
- Создали CRUD для Team
- Все простестили и проработали
Допустили и решили пару систематических ошибок, повторили основы написания.
Ждите продолжения!
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
@Shikin_Anatoliy - респект и уважуха
Please open Telegram to view this post
VIEW IN TELEGRAM
@LazyCollection в Hibernate
Аннотация @LazyCollection управляет стратегией ленивой загрузки для коллекций (например, @OneToMany, @ManyToMany) в Hibernate. Определяет, когда и как должны загружаться связанные сущности.
Пакет: org.hibernate.annotations
Применяется к: полям-коллекциям (List, Set, Map и др.) с аннотациями @OneToMany или @ManyToMany.
Параметры и настройки
Аннотация принимает один обязательный параметр — value, который может быть одним из следующих вариантов:
LazyCollectionOption.TRUE (по умолчанию для @OneToMany и @ManyToMany):
Коллекция загружается лениво (при первом обращении).
Используется прокси-объект (PersistentBag, PersistentSet).
LazyCollectionOption.EXTRA:
"Сверхленивая" загрузка: Hibernate загружает только необходимые данные при вызове методов коллекции (например, size(), contains()).
Полезно для больших коллекций, чтобы избежать полной загрузки.
LazyCollectionOption.FALSE:
Коллекция загружается жадно (eager loading), аналогично fetch = FetchType.EAGER.
Не рекомендуется для больших коллекций из-за риска N+1 проблемы.
Жизненный цикл и обработка
Инициализация прокси:
При загрузке родительской сущности коллекция заменяется прокси (реализацией Hibernate).
Прокси перехватывает вызовы методов (например, getItems()) и загружает данные.
Загрузка данных:
Для TRUE: при первом обращении к коллекции выполняется SQL-запрос.
Для EXTRA: методы вроде size() генерируют SELECT COUNT(*), а не загружают все элементы.
Сессия и LazyInitializationException:
Если коллекция запрашивается после закрытия сессии, возникнет исключение (если не используется OpenSessionInView).
Механизмы Hibernate и Spring Boot
Глобальная настройка ленивой загрузки:
Параметр spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true (не рекомендуется, приводит к N+1).
spring.jpa.open-in-view=true (держит сессию открытой до конца HTTP-запроса).
Интеграция с FetchType:
@LazyCollection переопределяет поведение fetch в @OneToMany:
Оптимизация запросов:
Для EXTRA Hibernate использует:
SELECT COUNT(*) FROM orders WHERE user_id = ? — для collection.size().
SELECT id FROM orders WHERE user_id = ? LIMIT 1 — для collection.isEmpty().
Примеры использования
Ленивая загрузка с проверкой размера без загрузки элементов:
Отключение ленивой загрузки (редкий случай):
Ограничения и лучшие практики
N+1 проблема: Даже с LazyCollectionOption.TRUE при обходе коллекции (for (Order o : user.getOrders())) выполняется один запрос для загрузки всех элементов. Решение: @EntityGraph или JOIN FETCH.
EXTRA не поддерживает List.get(index): Для этого требуется полная загрузка.
Тестирование: В тестах с закрытой сессией используйте Hibernate.initialize(collection).
#Java #Training #Hard #Spring #Hibernate #LazyCollection
Аннотация @LazyCollection управляет стратегией ленивой загрузки для коллекций (например, @OneToMany, @ManyToMany) в Hibernate. Определяет, когда и как должны загружаться связанные сущности.
Пакет: org.hibernate.annotations
Применяется к: полям-коллекциям (List, Set, Map и др.) с аннотациями @OneToMany или @ManyToMany.
Параметры и настройки
Аннотация принимает один обязательный параметр — value, который может быть одним из следующих вариантов:
LazyCollectionOption.TRUE (по умолчанию для @OneToMany и @ManyToMany):
Коллекция загружается лениво (при первом обращении).
Используется прокси-объект (PersistentBag, PersistentSet).
LazyCollectionOption.EXTRA:
"Сверхленивая" загрузка: Hibernate загружает только необходимые данные при вызове методов коллекции (например, size(), contains()).
Полезно для больших коллекций, чтобы избежать полной загрузки.
LazyCollectionOption.FALSE:
Коллекция загружается жадно (eager loading), аналогично fetch = FetchType.EAGER.
Не рекомендуется для больших коллекций из-за риска N+1 проблемы.
Жизненный цикл и обработка
Инициализация прокси:
При загрузке родительской сущности коллекция заменяется прокси (реализацией Hibernate).
Прокси перехватывает вызовы методов (например, getItems()) и загружает данные.
Загрузка данных:
Для TRUE: при первом обращении к коллекции выполняется SQL-запрос.
Для EXTRA: методы вроде size() генерируют SELECT COUNT(*), а не загружают все элементы.
Сессия и LazyInitializationException:
Если коллекция запрашивается после закрытия сессии, возникнет исключение (если не используется OpenSessionInView).
Механизмы Hibernate и Spring Boot
Глобальная настройка ленивой загрузки:
Параметр spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true (не рекомендуется, приводит к N+1).
spring.jpa.open-in-view=true (держит сессию открытой до конца HTTP-запроса).
Интеграция с FetchType:
@LazyCollection переопределяет поведение fetch в @OneToMany:
@OneToMany(fetch = FetchType.EAGER) // Игнорируется, если есть @LazyCollection
@LazyCollection(LazyCollectionOption.TRUE)
private List<Order> orders;
Оптимизация запросов:
Для EXTRA Hibernate использует:
SELECT COUNT(*) FROM orders WHERE user_id = ? — для collection.size().
SELECT id FROM orders WHERE user_id = ? LIMIT 1 — для collection.isEmpty().
Примеры использования
Ленивая загрузка с проверкой размера без загрузки элементов:
@OneToMany
@LazyCollection(LazyCollectionOption.EXTRA)
private Set<Comment> comments; // Для comments.size() не загружает все комментарии
Отключение ленивой загрузки (редкий случай):
@OneToMany
@LazyCollection(LazyCollectionOption.FALSE) // Аналог FetchType.EAGER
private List<Post> posts;
Ограничения и лучшие практики
N+1 проблема: Даже с LazyCollectionOption.TRUE при обходе коллекции (for (Order o : user.getOrders())) выполняется один запрос для загрузки всех элементов. Решение: @EntityGraph или JOIN FETCH.
EXTRA не поддерживает List.get(index): Для этого требуется полная загрузка.
Тестирование: В тестах с закрытой сессией используйте Hibernate.initialize(collection).
#Java #Training #Hard #Spring #Hibernate #LazyCollection
Что выведет код?
#Tasks
import java.util.HashMap;
public class Task140425 {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put(null, 1);
map.put("null", 2);
map.put(null, 3);
System.out.println(map.get(null) + " " + map.get("null"));
}
}
#Tasks
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩💻
Какой метод используется для преобразования строки в массив символов?
Какой метод используется для преобразования строки в массив символов?
Anonymous Quiz
4%
getChars()
83%
toCharArray()
6%
split()
6%
chars()
@LazyToOne в Hibernate
Аннотация @LazyToOne управляет стратегией ленивой загрузки для ассоциаций @ManyToOne и @OneToOne в Hibernate. В отличие от стандартного FetchType.LAZY, она позволяет более гибко настраивать механизм проксирования и инициализации связанных сущностей.
Пакет: org.hibernate.annotations
Применяется к: полям или методам с аннотациями @ManyToOne или @OneToOne.
1. Параметры и настройки
Аннотация @LazyToOne принимает один обязательный параметр — value, который может быть одним из следующих вариантов:
Доступные варианты загрузки:
LazyToOneOption.PROXY (по умолчанию, если FetchType.LAZY):
Создается прокси-объект, который загружает данные только при первом обращении.
Если связанная сущность уже удалена (и @ManyToOne nullable), может возникнуть LazyInitializationException.
LazyToOneOption.NO_PROXY:
Использует байткодовую модификацию (требует инструментирования, например, через javassist).
Позволяет избежать некоторых проблем с прокси, но сложнее в настройке.
LazyToOneOption.FALSE:
Эквивалентно FetchType.EAGER — загружает сущность сразу.
2. Жизненный цикл и обработка
При загрузке сущности:
Если PROXY → Hibernate подставляет прокси-объект, не загружая данные из БД.
Если NO_PROXY → генерируется специальный подкласс (требует hibernate.bytecode.provider=javassist).
При первом обращении:
Прокси инициализируется и выполняет SQL-запрос.
При закрытии сессии:
Если сессия закрыта до обращения к полю → LazyInitializationException.
Отличие от стандартного FetchType.LAZY
Обычный LAZY в @ManyToOne/@OneToOne не всегда работает (особенно если optional=false).
@LazyToOne дает больше контроля над механизмом ленивой загрузки.
3. Механизмы Hibernate и Spring Boot
Настройки, влияющие на @LazyToOne
hibernate.bytecode.provider (для NO_PROXY):
Открытие сессии в View (OpenSessionInView)
``
spring.jpa.open-in-view=true # Держит сессию открытой до конца HTTP-запроса
Позволяет избежать LazyInitializationException в веб-приложениях.
```
Глобальная настройка ленивой загрузки
4. Примеры использования
Пример 1: Ленивая загрузка с прокси (PROXY)
Пример 2: Ленивая загрузка без прокси (NO_PROXY)
#Java #Training #Hard #Spring #Hibernate #LazyToOne
Аннотация @LazyToOne управляет стратегией ленивой загрузки для ассоциаций @ManyToOne и @OneToOne в Hibernate. В отличие от стандартного FetchType.LAZY, она позволяет более гибко настраивать механизм проксирования и инициализации связанных сущностей.
Пакет: org.hibernate.annotations
Применяется к: полям или методам с аннотациями @ManyToOne или @OneToOne.
1. Параметры и настройки
Аннотация @LazyToOne принимает один обязательный параметр — value, который может быть одним из следующих вариантов:
Доступные варианты загрузки:
LazyToOneOption.PROXY (по умолчанию, если FetchType.LAZY):
Создается прокси-объект, который загружает данные только при первом обращении.
Если связанная сущность уже удалена (и @ManyToOne nullable), может возникнуть LazyInitializationException.
LazyToOneOption.NO_PROXY:
Использует байткодовую модификацию (требует инструментирования, например, через javassist).
Позволяет избежать некоторых проблем с прокси, но сложнее в настройке.
LazyToOneOption.FALSE:
Эквивалентно FetchType.EAGER — загружает сущность сразу.
2. Жизненный цикл и обработка
При загрузке сущности:
Если PROXY → Hibernate подставляет прокси-объект, не загружая данные из БД.
Если NO_PROXY → генерируется специальный подкласс (требует hibernate.bytecode.provider=javassist).
При первом обращении:
Прокси инициализируется и выполняет SQL-запрос.
При закрытии сессии:
Если сессия закрыта до обращения к полю → LazyInitializationException.
Отличие от стандартного FetchType.LAZY
Обычный LAZY в @ManyToOne/@OneToOne не всегда работает (особенно если optional=false).
@LazyToOne дает больше контроля над механизмом ленивой загрузки.
3. Механизмы Hibernate и Spring Boot
Настройки, влияющие на @LazyToOne
hibernate.bytecode.provider (для NO_PROXY):
spring.jpa.properties.hibernate.bytecode.provider=javassist
Без этого NO_PROXY может не работать.
Открытие сессии в View (OpenSessionInView)
``
spring.jpa.open-in-view=true # Держит сессию открытой до конца HTTP-запроса
Позволяет избежать LazyInitializationException в веб-приложениях.
```
Глобальная настройка ленивой загрузки
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true # Не рекомендуется!
(Может привести к N+1 и утечкам памяти.)
4. Примеры использования
Пример 1: Ленивая загрузка с прокси (PROXY)
@Entity
public class Order {
@ManyToOne(fetch = FetchType.LAZY) // Стандартный LAZY
@LazyToOne(LazyToOneOption.PROXY) // Явное указание прокси
private User user;
}
Пример 2: Ленивая загрузка без прокси (NO_PROXY)
@Entity
public class Employee {
@OneToOne(fetch = FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY) // Требует инструментирования
private ParkingSpot parkingSpot;
}
#Java #Training #Hard #Spring #Hibernate #LazyToOne
@Loader в Hibernate
Аннотация @Loader позволяет переопределить стандартный SQL-запрос, который Hibernate использует для загрузки сущности из базы данных.
Это полезно для сложных сценариев, когда требуется:
Загружать данные с помощью кастомного SQL (вместо SELECT * FROM table).
Оптимизировать запросы (например, использовать JOIN или подзапросы).
Загружать сущности через хранимые процедуры.
Пакет: org.hibernate.annotations
Применяется к: классу сущности (@Entity).
Параметры и настройки
namedQuery: Именованный запрос (определённый через @NamedQuery).
query: Собственный SQL-запрос (нативный или HQL).
Примеры:
Использование именованного запроса (namedQuery)
Прямое указание SQL (query)
Жизненный цикл и обработка
Когда выполняется кастомный запрос?
При загрузке сущности по ID:
session.get(User.class, 1) → выполняется запрос из @Loader.
При ленивой загрузке прокси:
Если сущность загружается через прокси (например, @ManyToOne с FetchType.LAZY), @Loader не применяется.
Ограничения
Запрос должен возвращать ровно одну сущность.
Параметры:
Для namedQuery — порядковый номер параметра (?1).
Для query — можно использовать ? или именованные параметры (:id).
Механизмы Hibernate и Spring Boot
Интеграция с @NamedQuery:
Если @Loader ссылается на namedQuery, запрос должен быть определён в той же сущности.
Нативные запросы vs HQL:
Если query начинается с SELECT *, Hibernate обрабатывает его как нативный.
Для HQL используйте синтаксис "FROM EntityName WHERE ...".
Влияние кеширования:
@Loader не отключает кеш второго уровня. Если сущность есть в кеше, запрос не выполнится.
Примеры использования
Пример 1: Оптимизированная загрузка с JOIN
Пример 2: Загрузка через хранимую процедуру
Ограничения и лучшие практики
Когда использовать @Loader?
Сложные условия загрузки (например, фильтрация по статусу).
Оптимизация запросов (избегание N+1 через JOIN).
Интеграция с legacy-кодом (хранимые процедуры).
#Java #Training #Hard #Spring #Hibernate #Loader
Аннотация @Loader позволяет переопределить стандартный SQL-запрос, который Hibernate использует для загрузки сущности из базы данных.
Это полезно для сложных сценариев, когда требуется:
Загружать данные с помощью кастомного SQL (вместо SELECT * FROM table).
Оптимизировать запросы (например, использовать JOIN или подзапросы).
Загружать сущности через хранимые процедуры.
Пакет: org.hibernate.annotations
Применяется к: классу сущности (@Entity).
Параметры и настройки
namedQuery: Именованный запрос (определённый через @NamedQuery).
query: Собственный SQL-запрос (нативный или HQL).
Примеры:
Использование именованного запроса (namedQuery)
@Entity
@Loader(namedQuery = "findUserById")
@NamedQuery(name = "findUserById", query = "SELECT u FROM User u WHERE u.id = ?1")
public class User { ... }
Прямое указание SQL (query)
@Entity
@Loader(query = "SELECT * FROM users WHERE user_id = ?1 AND is_active = true")
public class User { ... }
Жизненный цикл и обработка
Когда выполняется кастомный запрос?
При загрузке сущности по ID:
session.get(User.class, 1) → выполняется запрос из @Loader.
При ленивой загрузке прокси:
Если сущность загружается через прокси (например, @ManyToOne с FetchType.LAZY), @Loader не применяется.
Ограничения
Запрос должен возвращать ровно одну сущность.
Параметры:
Для namedQuery — порядковый номер параметра (?1).
Для query — можно использовать ? или именованные параметры (:id).
Механизмы Hibernate и Spring Boot
Интеграция с @NamedQuery:
Если @Loader ссылается на namedQuery, запрос должен быть определён в той же сущности.
Нативные запросы vs HQL:
Если query начинается с SELECT *, Hibernate обрабатывает его как нативный.
Для HQL используйте синтаксис "FROM EntityName WHERE ...".
Влияние кеширования:
@Loader не отключает кеш второго уровня. Если сущность есть в кеше, запрос не выполнится.
Примеры использования
Пример 1: Оптимизированная загрузка с JOIN
@Entity
@Loader(query = """
SELECT u.* FROM users u
LEFT JOIN user_settings s ON u.id = s.user_id
WHERE u.id = ?1
""")
public class User { ... }
Пример 2: Загрузка через хранимую процедуру
@Entity
@Loader(query = "CALL load_user_by_id(:id)")
public class User { ... }
Ограничения и лучшие практики
Когда использовать @Loader?
Сложные условия загрузки (например, фильтрация по статусу).
Оптимизация запросов (избегание N+1 через JOIN).
Интеграция с legacy-кодом (хранимые процедуры).
#Java #Training #Hard #Spring #Hibernate #Loader
Что выведет код?
#Tasks
import java.util.HashMap;
import java.util.Map;
public class Task150425 {
public static void main(String[] args) {
Map<StringBuilder, Integer> map = new HashMap<>();
StringBuilder key = new StringBuilder("Key");
map.put(key, 1);
key.append("Modified");
System.out.println(map.get(key));
System.out.println(map.get(new StringBuilder("Key")));
}
}
#Tasks
Вопросы с собеседования 👩💻
Что делает метод 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