Java for Beginner
672 subscribers
541 photos
155 videos
12 files
827 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
Аннотация @EntityListeners

Аннотация @EntityListeners является частью спецификации JPA (Jakarta Persistence API) и позволяет привязать кастомные слушатели (listeners) к сущностям JPA.

Эти слушатели могут перехватывать события жизненного цикла сущности, такие как:
@PrePersist (перед сохранением)
@PostPersist (после сохранения)
@PreUpdate (перед обновлением)
@PostUpdate (после обновлением)
@PreRemove (перед удалением)
@PostRemove (после удалением)
@PostLoad (после загрузкой из БД)

Аннотация находится в пакете jakarta.persistence и применяется на уровне класса сущности.

Параметры аннотации

value (обязательный)
Тип: Массив классов (Class<?>[])
Описание: Принимает один или несколько классов-слушателей, которые должны реализовывать callback-методы JPA.

Пример:
@Entity
@EntityListeners({AuditListener.class, CacheInvalidationListener.class})
public class User {
// поля сущности
}


Жизненный цикл слушателей

Регистрация слушателей
При загрузке метаданных JPA провайдер (Hibernate) регистрирует указанные классы-слушатели для сущности.
Вызов callback-методов
При наступлении соответствующего события жизненного цикла JPA вызывает методы слушателей в порядке их объявления.


Порядок выполнения
Если для сущности определено несколько слушателей, их методы выполняются в порядке объявления в аннотации.
Глобальные слушатели (зарегистрированные в orm.xml) выполняются после локальных.


Механизмы работы в Spring

1. Интеграция с Spring
Spring автоматически поддерживает DI в JPA Entity Listeners, если они являются Spring-бинами.

Для этого нужно:
Пометить класс-слушатель как @Component
Зарегистрировать его в Spring-контексте


2. Пример Spring-совместимого слушателя
@Component
public class AuditListener {

@PrePersist
public void prePersist(Object entity) {
System.out.println("PrePersist: " + entity);
}

@PreUpdate
public void preUpdate(Object entity) {
System.out.println("PreUpdate: " + entity);
}
}


3. Конфигурация в Spring Boot
Spring Boot автоматически настраивает поддержку Entity Listeners через:
Автоконфигурацию JPA (HibernateJpaAutoConfiguration)
Поддержку инъекции зависимостей в слушатели


Варианты использования

1. Аудит изменений
public class AuditListener {
@PrePersist
public void setCreationDate(Object entity) {
if (entity instanceof Auditable) {
((Auditable) entity).setCreatedAt(LocalDateTime.now());
}
}
}


2. Валидация перед сохранением
public class ValidationListener {
@PrePersist
@PreUpdate
public void validate(Object entity) {
if (entity instanceof Validatable) {
((Validatable) entity).validate();
}
}
}


3. Кеширование
public class CacheListener {
@PostPersist
@PostUpdate
@PostRemove
public void invalidateCache(Object entity) {
CacheManager.evict(entity.getClass(), entity.getId());
}
}


Ограничения и особенности

Контекст выполнения
Callback-методы выполняются в том же контексте транзакции, что и основная операция.

Исключения
Выброс исключения в callback-методе приводит к откату транзакции.

Порядок выполнения
Методы выполняются в порядке:

Callback-методы самой сущности
Локальные
@EntityListeners
Глобальные слушатели


DI ограничения

В чистом JPA слушатели не поддерживают инъекцию зависимостей
В Spring DI работает только для Spring-бинов


#Java #Training #Hard #Spring #SpringDataJPA #EntityListeners
Что выведет код?

import java.util.function.Function;

public class Task030425 {
public static void main(String[] args) {
Function<Integer, Integer> func = x -> x % 2 == 0 ? x * 2 : x / 2;
System.out.println(func.apply(5));
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
10%
10
8%
5
60%
2
23%
Exception какой-нибудь
Диалог с ревью🤪

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩‍💻

Какой метод возвращает случайное число от 0 до 1?
Anonymous Quiz
17%
System.random()
4%
Math.next()
17%
Random.nextDouble()
62%
Math.random()
Аннотация @Projection

Аннотация
@Projection используется в Spring Data для определения проекций - специальных интерфейсов или классов, которые позволяют выбирать только определенные поля из сущностей.

Это полезно для:
Оптимизации запросов (избегания select *)
Создания DTO на лету
Кастомизации JSON-представления REST API


Проекции находятся в пакете org.springframework.data.rest.core.config.Projection и применяются к интерфейсам или классам.


Параметры аннотации

types (обязательный)
Тип: Class<?>[]
Описание: Указывает сущности, к которым применяется проекция


Пример:
@Projection(types = {User.class})
public interface UserSummary {
String getUsername();
String getEmail();
}


name (необязательный)
Тип: String
Описание: Задает имя проекции для использования в Spring Data REST


Пример:
@Projection(name = "summary", types = User.class)
public interface UserSummary {...}


Типы проекций

1. Интерфейсные проекции

Наиболее распространенный подход:
@Projection(types = User.class)
public interface UserView {
String getUsername();
String getEmail();

// Можно включать связанные сущности
@Value("#{target.department.name}")
String getDepartmentName();
}


2. Классовые проекции (DTO)
Используются классы вместо интерфейсов:
@Projection(types = User.class)
public class UserDto {
private final String username;
private final String email;

public UserDto(String username, String email) {
this.username = username;
this.email = email;
}

// Геттеры
}


3. Динамические проекции
Можно создавать проекции на лету через SpEL:
@Projection(types = User.class)
public interface DynamicUserView {
@Value("#{target.username + ' (' + target.email + ')'}")
String getDisplayName();
}


Жизненный цикл проекций

Объявление проекции
Создается интерфейс/класс с аннотацией @Projection
Определяются методы, соответствующие полям сущности


Использование в репозитории
Spring Data создает прокси-реализацию при выполнении запроса

Преобразование результатов
После выполнения запроса результаты маппятся на проекцию

Механизмы Spring Data

1. Автоматический маппинг

Spring Data автоматически:
Анализирует методы проекции
Создает соответствующий SQL (только выбранные поля)
Преобразует результат в проекцию


2. Интеграция с репозиториями
public interface UserRepository extends JpaRepository<User, Long> {
<T> List<T> findBy(Class<T> type);
UserSummary findSummaryById(Long id);
}


3. Поддержка в Spring Data REST

Проекции можно активировать через параметр запроса:
GET /users/1?projection=summary


Примеры использования


1. Базовый пример
@Entity
public class User {
private Long id;
private String username;
private String email;
// геттеры/сеттеры
}

@Projection(types = User.class)
public interface UserSummary {
String getUsername();
String getEmail();
}

// В репозитории
UserSummary findSummaryById(Long id);


2. Комплексная проекция
@Projection(types = {User.class, Department.class})
public interface UserDetailView {
String getUsername();

@Value("#{target.department.name}")
String getDepartmentName();

default String getDisplayInfo() {
return getUsername() + " from " + getDepartmentName();
}
}


3. Вложенные проекции
@Projection(types = Order.class)
public interface OrderView {
String getOrderNumber();

@Value("#{target.customer}")
CustomerView getCustomer();
}

@Projection(types = Customer.class)
public interface CustomerView {
String getName();
}


Настройки Spring Boot

Автоконфигурация
Spring Boot автоматически настраивает поддержку проекций через SpringDataWebConfiguration

Ручная регистрация
Можно явно зарегистрировать проекции:
@Configuration
public class ProjectionConfig {
@Bean
public ProjectionDefinitionRegistrar projectionRegistrar() {
return registrar -> {
registrar.addProjection(UserSummary.class);
};
}
}


Настройка REST

В application.properties:
spring.data.rest.default-projection=summary


#Java #Training #Hard #Spring #SpringDataJPA #Projection
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Аннотация @Any в Spring

Аннотация @Any относится к пакету org.hibernate.annotations (Hibernate, не Spring), но часто используется в Spring-приложениях, работающих с JPA/Hibernate. Она применяется для обозначения полиморфных ассоциаций, когда сущность может ссылаться на разные типы объектов.

@Any позволяет моделировать связь, где поле может содержать экземпляр любой сущности (из заданного набора), а не только строго определённого типа (как в @ManyToOne или @OneToOne).

Параметры и настройки

Аннотация @Any сама по себе не принимает параметров, но требует дополнительных аннотаций для корректной работы:

@AnyMetaDef (или @AnyMetaDefs для нескольких определений) – определяет метаданные для полиморфной связи:

name (обязательный)уникальное имя определения, которое используется в @Any.
metaType (по умолчанию String)тип идентификатора, хранящего информацию о классе (обычно String или Integer).
idType (обязательный)тип первичного ключа связанных сущностей (например, Long).
metaValuesмассив @MetaValue, где каждое значение связывает идентификатор класса с конкретной сущностью.

Пример:
@AnyMetaDef(
name = "animalMetaDef",
metaType = "string",
idType = "long",
metaValues = {
@MetaValue(value = "DOG", targetEntity = Dog.class),
@MetaValue(value = "CAT", targetEntity = Cat.class)
}
)


@JoinColumn указывает столбец в БД, хранящий ID связанной сущности.
@Column (опционально)указывает столбец, хранящий тип сущности (если метаданные используют отдельный столбец).

Пример использования
@Entity
public class Zoo {
@Id
private Long id;

@Any(metaDef = "animalMetaDef", metaColumn = @Column(name = "animal_type"))
@JoinColumn(name = "animal_id")
private Animal animal; // Может быть Dog или Cat
}


Жизненный цикл @Any

Загрузка (@PostLoad)
Hibernate определяет тип сущности по значению в metaColumn и загружает соответствующий объект.

Сохранение (@PrePersist/@PreUpdate)
перед сохранением Hibernate записывает:
ID сущности в animal_id.
Класс сущности (например, "DOG") в animal_type.


Удаление
каскадное удаление не поддерживается автоматически, нужно обрабатывать вручную.

Механизмы Spring и Spring Boot, связанные с @Any

Поскольку @Any – это аннотация Hibernate, её работа зависит от:
spring.jpa.hibernate.ddl-auto (в application.properties/application.yml) – если стоит update или create, Hibernate автоматически создаст таблицы с полями animal_id и animal_type.
spring.jpa.show-sql – полезно для отладки запросов, связанных с полиморфными ассоциациями.
EntityManager – Spring Boot автоматически настраивает его, и через него происходят все операции с @Any.


Ограничения и альтернативы
Нет встроенной поддержки в Spring Data JPA – репозитории не могут автоматически генерировать запросы для @Any.

Альтернативы:
@OneToMany + наследование (@Inheritance(strategy = InheritanceType.SINGLE_TABLE)) – если типы известны заранее.
@ElementCollection + Map<String, Object> – если полиморфизм нужен только для хранения данных.

#Java #Training #Hard #Spring #Hibernate #Any
Что выведет код?

import java.util.function.Predicate;

public class Task040425 {
public static void main(String[] args) {
Predicate<String> p1 = s -> s.length() > 4;
Predicate<String> p2 = s -> s.startsWith("J");

System.out.println(p1.and(p2).test("Java"));
}
}


#Tasks
Бедные, и ведь не отойти 😂

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩‍💻

Какой метод преобразует объект в строку в StringBuilder?
Anonymous Quiz
12%
getString()
8%
build()
73%
toString()
6%
convert()
Аннотация @BatchSize в Spring (Hibernate)

Аннотация @BatchSize принадлежит пакету org.hibernate.annotations и используется для оптимизации загрузки коллекций или прокси-объектов в Hibernate. Она позволяет загружать элементы пакетно (batch), уменьшая количество SQL-запросов (проблема N+1).

Применяется в двух случаях:
Для коллекций (@OneToMany, @ManyToMany) – загружает несколько связанных коллекций одним запросом.
Для лениво загружаемых сущностей (
@ManyToOne, @OneToOne) – загружает несколько прокси-объектов партиями.

Параметры и настройки
У аннотации есть один обязательный параметр - size: размер пакета (сколько элементов загружать за один SQL-запрос), обычно 10, 20, 50.

Примеры использования
Пакетная загрузка коллекций (N+1 Problem Fix)
@Entity
public class Author {
@Id
private Long id;

@OneToMany(mappedBy = "author")
@BatchSize(size = 10) // Загружает до 10 книг за один запрос
private List<Book> books;
}


Как работает:
Если загружается 100 авторов, без @BatchSize Hibernate выполнит 100+1 запрос (1 для авторов + 100 для книг каждого).
С
@BatchSize(size=10) Hibernate сделает 1 запрос для авторов + 10 запросов для книг (каждый запрос загружает книги для 10 авторов).

Пакетная загрузка ленивых сущностей
@Entity
public class Book {
@Id
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@BatchSize(size = 5) // Загружает авторов пачками по 5
private Author author;
}


Как работает:
При обращении к book.getAuthor(), Hibernate не загружает автора сразу, а ждёт, пока не потребуются несколько авторов.
Когда накопятся 5 ленивых прокси, Hibernate выполнит один запрос вида:


SELECT * FROM author WHERE id IN (1, 2, 3, 4, 5)


Жизненный цикл

Инициализация прокси/коллекции – Hibernate откладывает загрузку до первого обращения.
Пакетная загрузка – при достижении size или принудительной инициализации (например, Hibernate.initialize()).
Кэширование – загруженные объекты помещаются в кэш первого уровня (Session).


Настройки Hibernate в Spring Boot

@BatchSize работает на уровне Hibernate, но Spring Boot позволяет управлять его поведением через:
spring.jpa.properties.hibernate.default_batch_fetch_size (в
application.properties)

spring.jpa.properties.hibernate.default_batch_fetch_size=20
Устанавливает глобальный размер пакета для всех ленивых загрузок.


Если
@BatchSize указан на поле, он имеет приоритет.

Оптимизация запросов

JOIN FETCH (в JPQL) загружает данные одним запросом, но может привести к Cartesian Product.
@BatchSize даёт баланс между количеством запросов и объёмом данных.
@BatchSize можно комбинировать с @EntityGraph, но обычно @EntityGraph полностью отключает ленивую загрузку.

#Java #Training #Hard #Spring #Hibernate #BatchSize
This media is not supported in your browser
VIEW IN TELEGRAM
Всем привет! 😉

Вот и очередная неделя позади... Можно расслабиться и покодить для себя 😁

Сегодня мы посмотрим очередную подборку смешных "выходных" видео, а вот завтра вновь встретимся и полайфкодим!
🤓

Напишем тестовое задание одной из реальных компаний 🫡

Так что планируем завтра встретиться!


А в остальном всем прекрасных выходных!🙏☀️
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Команда запустила тестирование с заказчиком 😎

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM