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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Пишем погодного телеграм-бота! ☀️

Встреча от 30.03.2025

Запись встречи -
YOUTUBE
RUTUBE

На сегодняшней встрече мы написали своего бота.
🤖

При написании мы узнали и повторили:
🔜 Как вообще пишут бота и с какими библиотеками.
🔜 Как работает логика бота.
🔜 Как по REST передают json и как его парсить.
🔜 Настроили свой кэш и шедулер.
🔜 Как всегда допустил немного ошибок и успешно их решил)

Кстати в гите более полная версия того бота который я запускал Вам для теста!
Ссылка на Git - https://github.com/Oleborn/WeatherChatBot

Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!

Всем спасибо за участие и то что пришли, для меня это важно!

Надеюсь вы напишете своих ботов и обязательно похвастаете перед нами 😉
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Аннотация @CreatedBy

Аннотация @CreatedBy используется в Spring Data для автоматического заполнения поля информацией о пользователе, создавшем сущность. Это часть механизма аудита Spring Data, позволяющего автоматически отслеживать, кто и когда создавал или изменял сущности. Аннотация находится в пакете org.springframework.data.annotation.

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

Аннотация @CreatedBy не имеет параметров. Она применяется к полям сущности, которые должны автоматически заполняться информацией о создателе.

Пример использования:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Document {
@CreatedBy
private String createdBy;

// Другие поля
}


Жизненный цикл аннотации

Инициализация:
Аннотация активируется при включении аудита через @EnableJpaAuditing
Требуется регистрация AuditingEntityListener для сущности


Выполнение:
Перед сохранением новой сущности (при вызове save())
Spring автоматически определяет текущего пользователя и устанавливает значение поля


Обновление:
Поле заполняется только при создании сущности
Не изменяется при последующих обновлениях


Механизмы Spring и настройки Spring Boot

AuditingEntityListener:
Класс, обрабатывающий события жизненного цикла сущности
Автоматически заполняет аннотированные поля


AuditorAware:
Интерфейс для получения информации о текущем пользователе
Требуется реализация для работы
@CreatedBy

EnableJpaAuditing:
Аннотация для активации механизма аудита

Настройки Spring Boot

Активация аудита:
@Configuration
@EnableJpaAuditing
public class AuditConfig {
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.map(Authentication::getName);
}
}


Конфигурация сущности:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Order {
@CreatedBy
private String createdBy;

@CreatedDate
private LocalDateTime createdDate;

// Другие поля
}


Настройки безопасности (если используется Spring Security):
spring.security.user.name=admin
spring.security.user.password=secret


Варианты настройки

Типы полей:
Может использоваться с любым типом (String, Long, UUID)
Чаще всего используется String для хранения имени пользователя


Интеграция с Spring Security:
Автоматическое получение имени текущего пользователя

Пример реализации AuditorAware:
public class SecurityAuditorAware implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
return Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getName);
}
}


Кастомные реализации:
Возможность использовать ID пользователя вместо имени
Интеграция с кастомными системами аутентификации


Комбинирование с другими аннотациями аудита:
@CreatedBy
private String createdBy;

@CreatedDate
private LocalDateTime createdDate;

@LastModifiedBy
private String lastModifiedBy;

@LastModifiedDate
private LocalDateTime lastModifiedDate;


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

import java.util.LinkedList;

public class Task310325 {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
list.add(1);
list.add(2);
list.addFirst(3);
list.removeLast();

System.out.println(list.get(1));
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
33%
1
22%
2
35%
3
11%
Какой-то Exception
Это хорошо когда есть за кем ходить😂

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Аннотация @CreatedDate

Аннотация @CreatedDate используется в Spring Data для автоматического заполнения поля датой и временем создания сущности. Это часть механизма аудита Spring Data, который позволяет автоматически отслеживать временные метки создания и модификации сущностей. Аннотация находится в пакете org.springframework.data.annotation.

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

Аннотация @CreatedDate не имеет параметров. Она применяется к полям сущности, которые должны автоматически заполняться временем создания.

Пример использования:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Document {
@CreatedDate
private LocalDateTime createdAt;

// Другие поля
}


Поддерживаемые типы данных

Поле с аннотацией @CreatedDate может быть одного из следующих типов:
java.time.LocalDateTime
java.time.LocalDate
java.time.ZonedDateTime
java.util.Date
java.util.Calendar
java.sql.Timestamp
Long (для timestamp в миллисекундах)


Жизненный цикл аннотации

Инициализация:
Активируется при включении аудита через @EnableJpaAuditing
Требуется регистрация AuditingEntityListener для сущности


Выполнение:
Автоматически устанавливает текущую дату и время при первом сохранении сущности
Значение устанавливается один раз при создании и не изменяется при последующих обновлениях


Обновление:
Для отслеживания времени изменения следует использовать @LastModifiedDate

Механизмы Spring и настройки Spring Boot

AuditingEntityListener:
Обрабатывает события жизненного цикла сущности
Автоматически заполняет аннотированные поля датой/временем


EnableJpaAuditing:
Аннотация для активации механизма аудита

Настройки Spring Boot

Активация аудита в конфигурационном классе:
@Configuration
@EnableJpaAuditing
public class AuditConfig {
// Дополнительные настройки при необходимости
}


Конфигурация сущности:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Order {
@CreatedDate
private LocalDateTime createdAt;

@LastModifiedDate
private LocalDateTime updatedAt;

// Другие поля
}


Настройка часового пояса (опционально):
spring.jpa.properties.hibernate.jdbc.time_zone=UTC


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

Комбинирование с другими аннотациями аудита:
@CreatedDate
private LocalDateTime createdAt;

@CreatedBy
private String createdBy;

@LastModifiedDate
private LocalDateTime updatedAt;

@LastModifiedBy
private String updatedBy;


Использование разных типов даты/времени:
@CreatedDate
private Date createdAt; // java.util.Date

@CreatedDate
private Long createdTimestamp; // timestamp в миллисекундах


Кастомные форматы даты (при использовании с DTO):

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@CreatedDate
private LocalDateTime createdAt;


Использование в проекциях Spring Data:

public interface OrderProjection {
@Value("#{target.createdAt}")
String getFormattedCreatedAt();
}


Особенности работы

Одноразовое заполнение:

Значение устанавливается только при первом сохранении сущности
Не изменяется при последующих обновлениях


Точность времени:
Зависит от базы данных и JPA-провайдера
Для высокой точности рекомендуется использовать java.time типы


Синхронизация времени:
Время берется с сервера, где выполняется приложение
Для распределенных систем рекомендуется использовать единый источник времени

#Java #Training #Hard #Spring #SpringDataJPA #CreatedDate
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Аннотации @LastModifiedBy и @LastModifiedDate

Эти аннотации являются частью механизма аудита Spring Data и используются для автоматического отслеживания:
@LastModifiedBy - кто последним изменял сущность
@LastModifiedDate - когда были внесены последние изменения

Обе аннотации находятся в пакете org.springframework.data.annotation.

Аннотация @LastModifiedBy

Параметры
Как и @CreatedBy, аннотация не имеет параметров. Применяется к полям, которые должны хранить информацию о последнем редакторе.

Поддерживаемые типы
String (для имен пользователей)
Long/UUID (для ID пользователей)

Любой другой тип, возвращаемый реализацией AuditorAware

Пример использования
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Document {
@LastModifiedBy
private String lastModifiedBy;

// Другие поля
}


Аннотация @LastModifiedDate

Параметры
Не имеет параметров. Применяется к полям даты/времени.

Поддерживаемые типы
Те же, что и для @CreatedDate:
java.time типы (LocalDateTime, ZonedDateTime)
java.util.Date
Long (timestamp)


Пример использования
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Document {
@LastModifiedDate
private LocalDateTime lastModifiedAt;

// Другие поля
}


Комбинированное использование

Полный пример аудита
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Product {
@Id
private Long id;

@CreatedBy
private String createdBy;

@CreatedDate
private LocalDateTime createdAt;

@LastModifiedBy
private String lastModifiedBy;

@LastModifiedDate
private LocalDateTime lastModifiedAt;

// Бизнес-поля
private String name;
private BigDecimal price;
}


Особенности поведения

Инициализация:
@CreatedBy/Date заполняются только при создании
@LastModifiedBy/Date обновляются при каждом изменении

Сценарий обновления:
product.setPrice(new BigDecimal("99.99"));
productRepository.save(product);
Поля lastModifiedBy/At будут автоматически обновлены
Поля createdBy/At останутся без изменений


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

Обязательная конфигурация
Активация аудита:
@SpringBootApplication
@EnableJpaAuditing
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}


Реализация AuditorAware (для @CreatedBy и @LastModifiedBy):
@Bean
public AuditorAware<String> auditorAware() {
return () -> Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getName);
}


Дополнительные настройки
Для JPA репозиториев:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true


Настройка формата даты (опционально):
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=UTC


Практические рекомендации


Для веб-приложений:
Комбинируйте с Spring Security для автоматического определения пользователя
Используйте DTO с аннотацией
@JsonFormat для красивого отображения дат

Для микросервисов:
Вместо имени пользователя можно хранить ID сервиса
Используйте единый часовой пояс (UTC) для всех сервисов


Оптимизация запросов:
@Query("SELECT p FROM Product p WHERE p.lastModifiedAt > :since")
List<Product> findRecentlyModified(@Param("since") LocalDateTime since);


Интеграция с историей изменений:
Можно создать отдельную таблицу для хранения полной истории изменений
Использовать
@PreUpdate и @PrePersist для дополнительного логирования

Ограничения и решения

Проблема: Не обновляется при косвенных изменениях
Решение: Явно вызывать save() или использовать
@Version

Проблема: Неточное время в кластере
Решение: Использовать NTP или временные сервисы


Проблема: Кастомные редакторы (например, системные задания)
Решение: Переопределить AuditorAware для специфических случаев


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

public class Task010425 {
public static void main(String[] args) {
double x = -2.5;
double result = Math.abs(Math.floor(x));
System.out.println(result);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
34%
2.0
20%
2.5
27%
3.0
20%
-3.0
Ну это конечно капец, а недельку настроиться?🤣

https://t.me/Java_for_beginner_dev

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

Какой метод используется для замены символов в строке?
Anonymous Quiz
93%
replace()
7%
swap()
0%
change()
0%
substitute()
Аннотация @Version

Аннотация @Version используется в JPA для реализации оптимистичной блокировки (optimistic locking) - механизма контроля параллельного доступа к данным без использования явных блокировок на уровне базы данных. Находится в пакете javax.persistence.

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

Аннотация не имеет параметров. Применяется к единственному полю сущности, которое должно быть:
Числовым типом (int, Integer, long, Long)
Типом java.sql.Timestamp


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

@Entity
public class Product {
@Id
private Long id;

@Version
private Integer version;

// другие поля
}


Жизненный цикл аннотации

Инициализация:
При создании сущности поле получает значение 0 (или текущее время для Timestamp)

Обновление:
При каждом обновлении сущности значение автоматически увеличивается на 1
JPA проверяет, что значение в БД совпадает с исходным значением перед обновлением


Конфликт:
Если значение в БД изменилось (другой транзакцией), выбрасывается OptimisticLockException

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

При чтении сущности:
Product product = em.find(Product.class, 1L);
// product.version = 1 (текущее значение в БД)


При обновлении:
product.setPrice(newPrice);
em.merge(product);


Выполняется SQL вида:
UPDATE product 
SET ..., version = version + 1
WHERE id = 1 AND version = 1


Если версия изменилась:
Количество обновленных строк = 0 → OptimisticLockException

Обработка исключений:

@ExceptionHandler(OptimisticLockException.class)
public ResponseEntity<String> handleConflict(OptimisticLockException ex) {
return ResponseEntity.status(HttpStatus.CONFLICT).body("Объект был изменен другим пользователем");
}


Практическое использование

Базовый сценарий:

@Service
@Transactional
public class ProductService {
public void updatePrice(Long id, BigDecimal newPrice) {
Product product = productRepository.findById(id).orElseThrow();
product.setPrice(newPrice);
// При коммите транзакции версия автоматически увеличится
}
}


Проверка версии вручную:

public void updateWithVersionCheck(Long id, Integer expectedVersion, Product update) {
Product product = productRepository.findById(id).orElseThrow();
if (!product.getVersion().equals(expectedVersion)) {
throw new OptimisticLockException("Версия не совпадает");
}
// ... обновление
}


Использование DTO:
public class ProductDto {
private Long id;
private Integer version;
// другие поля

public Product toEntity() {
Product product = new Product();
product.setId(this.id);
product.setVersion(this.version);
// ...
return product;
}
}


Особенности реализации

Типы полей:
Для числовых типов: последовательное увеличение
Для Timestamp: текущее время сервера

Поведение при:
Создании: устанавливается 0
Клонировании: версия не копируется
Удалении: проверка версии не выполняется (настраивается через
@OptimisticLocking)

Производительность:
Минимальные накладные расходы
Не требует блокировок в БД


Альтернативы и дополнения

Пессимистичная блокировка:
@Lock(LockModeType.PESSIMISTIC_WRITE)
Product findByIdForUpdate(Long id);


Дополнительные аннотации Hibernate:
@OptimisticLocking - для настройки поведения
@DynamicUpdate - обновлять только измененные поля

Кастомные стратегии:
Реализация собственного механизма через @PreUpdate

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

Аннотация @PersistenceContext используется для внедрения (inject) контейнера управляемых JPA-сущностей (EntityManager) в Spring-приложение. Она принадлежит к спецификации Jakarta Persistence API (JPA) и находится в пакете jakarta.persistence.

Spring автоматически управляет жизненным циклом EntityManager, обеспечивая корректное открытие и закрытие сессий, а также интеграцию с транзакциями.

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

name (необязательный)
Тип: String
Описание: Имя единицы персистентности (persistence-unit), если их несколько в persistence.xml.


Пример:
@PersistenceContext(name = "myPersistenceUnit")
private EntityManager entityManager;


unitName (необязательный)
Тип: String
Описание: Альтернатива name, явно указывает имя persistence-unit.

Пример:
@PersistenceContext(unitName = "myPersistenceUnit")
private EntityManager entityManager;


type (необязательный)
Тип: PersistenceContextType (TRANSACTION или EXTENDED)
Значение по умолчанию: TRANSACTION


Описание:

TRANSACTION (по умолчанию): EntityManager привязан к текущей транзакции и закрывается после её завершения.
EXTENDED: EntityManager живет дольше транзакции (используется в Stateful-бинах, например, в JSF).


Пример:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;


properties (необязательный)
Тип: Map<String, Object>
Описание: Дополнительные свойства для настройки EntityManager (например, hibernate.jdbc.batch_size).


Пример:
@PersistenceContext(properties = {
@PersistenceProperty(name = "hibernate.jdbc.batch_size", value = "20")
})
private EntityManager entityManager;


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

Инициализация
При старте Spring создает прокси для EntityManager, который делегирует вызовы реальному EntityManager только внутри транзакции.
Если используется EXTENDED, EntityManager сохраняет состояние между транзакциями.


Работа в транзакции
В режиме TRANSACTION (по умолчанию) EntityManager автоматически открывается при старте транзакции (@Transactional) и закрывается после её завершения.

Уничтожение
В режиме TRANSACTION EntityManager закрывается после завершения транзакции.
В режиме EXTENDED EntityManager живет до уничтожения бина (например, при завершении HTTP-сессии в веб-приложении).


Механизмы Spring и настройки Spring Boot

1. Как Spring Boot настраивает EntityManager?

Spring Boot автоматически создает EntityManagerFactory на основе:
Настроек DataSource (из application.properties).
JPA-провайдера (Hibernate по умолчанию).


2. Альтернативные варианты настройки

Несколько источников данных:
Если нужно несколько EntityManager, можно определить несколько @Bean в конфигурации:
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.domain");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return em;
}


Ручное управление транзакциями:
Можно использовать EntityManager без @Transactional, но тогда нужно вручную вызывать em.getTransaction().begin() и commit().

Аннотация @PersistenceUnit

Аннотация @PersistenceUnit используется для внедрения EntityManagerFactory (а не самого EntityManager). Полезна, когда требуется создавать EntityManager вручную.

Параметры

unitName (необязательный) – имя persistence-unit (если их несколько).

Пример использования
@PersistenceUnit
private EntityManagerFactory emf;

public void someMethod() {
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
// ... операции с БД ...
em.getTransaction().commit();
} finally {
em.close();
}
}


Когда использовать @PersistenceUnit вместо @PersistenceContext?

Если нужно полное управление жизненным циклом EntityManager (например, в batch-обработке).
Если требуется несколько EntityManager в одном методе.

#Java #Training #Hard #Spring #SpringDataJPA #PersistenceUnit #PersistenceContext