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
Аннотации @NamedNativeQuery и @NamedNativeQueries

Аннотации @NamedNativeQuery и @NamedNativeQueries используются в Java Persistence API (JPA) для определения именованных нативных SQL-запросов (Named Native Queries). Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).

@NamedNativeQuery: Позволяет определить один именованный нативный SQL-запрос.
@NamedNativeQueries: Позволяет определить несколько именованных нативных SQL-запросов для одной сущности.

Нативные запросы полезны, когда требуется использовать специфические для базы данных функции или оптимизировать выполнение запросов, которые сложно выразить через JPQL.

@NamedNativeQuery

Аннотация @NamedNativeQuery принимает следующие параметры:

name (обязательный):
Уникальное имя запроса. Обычно используется формат EntityName.queryName.
Пример: "User.findByEmailNative".

query (обязательный):

Строка, содержащая нативный SQL-запрос.
Пример: "SELECT * FROM users WHERE email = :email".


resultClass (необязательный):
Класс сущности, к которому будет маппиться результат запроса.
Пример: resultClass = User.class.


resultSetMapping (необязательный):
Имя маппинга результата, определенного с помощью @SqlResultSetMapping.
Используется, если результат запроса не соответствует напрямую сущности.


hints (необязательный):
Массив подсказок (hints), которые могут быть переданы провайдеру JPA (например, Hibernate) для настройки выполнения запроса.
Пример:
@QueryHint(name = "org.hibernate.cacheable", value = "true").

Пример использования:
@NamedNativeQuery(
name = "User.findByEmailNative",
query = "SELECT * FROM users WHERE email = :email",
resultClass = User.class,
hints = {
@QueryHint(name = "org.hibernate.cacheable", value = "true")
}
)


@NamedNativeQueries

Аннотация @NamedNativeQueries используется для группировки нескольких аннотаций @NamedNativeQuery. Она принимает массив @NamedNativeQuery.

Пример использования:
@NamedNativeQueries({
@NamedNativeQuery(
name = "User.findByEmailNative",
query = "SELECT * FROM users WHERE email = :email",
resultClass = User.class
),
@NamedNativeQuery(
name = "User.findAllActiveNative",
query = "SELECT * FROM users WHERE active = 1",
resultClass = User.class
)
})


Значения по умолчанию

Если параметры resultClass, resultSetMapping или hints не указаны, используются значения по умолчанию (отсутствие маппинга и пустой массив подсказок соответственно).

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

Использование нативного SQL:
Нативные запросы позволяют использовать специфические для базы данных функции и оптимизации.

Маппинг результатов:
Если результат запроса не соответствует напрямую сущности, можно использовать @SqlResultSetMapping для кастомизации маппинга.

Пример использования @SqlResultSetMapping:
@SqlResultSetMapping(
name = "UserMapping",
entities = @EntityResult(entityClass = User.class)
)
@NamedNativeQuery(
name = "User.findByEmailNative",
query = "SELECT * FROM users WHERE email = :email",
resultSetMapping = "UserMapping"
)


Кэширование запросов:
Для оптимизации производительности можно включить кэширование запросов через подсказки (hints).

Динамические нативные запросы:
Если именованные нативные запросы недостаточно гибки, можно использовать @Query с параметром nativeQuery = true в Spring Data JPA для определения запросов непосредственно в репозитории.

Пример использования @Query:
public interface UserRepository extends JpaRepository<User, Long> {
@Query(nativeQuery = true, value = "SELECT * FROM users WHERE email = :email")
User findByEmailNative(@Param("email") String email);
}


#Java #Training #Hard #Spring #SpringDataJPA #NamedNativeQuery #NamedNativeQueries
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Аннотации @Convert и @Converter

Аннотации @Convert и @Converter используются в Java Persistence API (JPA) для кастомизации маппинга атрибутов сущности на базу данных. Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).

@Converter: Позволяет определить класс, который реализует интерфейс AttributeConverter для преобразования атрибута сущности в тип, поддерживаемый базой данных, и наоборот.
@Convert: Позволяет применить конкретный конвертер к атрибуту сущности.

Эти аннотации полезны, когда требуется сохранить в базе данных сложные типы данных (например, перечисления, коллекции или пользовательские объекты), которые не поддерживаются напрямую JPA.

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

@Converter

Аннотация @Converter применяется к классу, который реализует интерфейс AttributeConverter. Она принимает следующие параметры:
autoApply (необязательный):
Если true, конвертер автоматически применяется ко всем атрибутам сущности, которые имеют соответствующий тип.
Если false, конвертер применяется только к тем атрибутам, которые явно аннотированы
@Convert.
По умолчанию: false.

Пример использования:
@Converter(autoApply = true)
public class StatusConverter implements AttributeConverter<Status, String> {
@Override
public String convertToDatabaseColumn(Status status) {
return status.name().toLowerCase();
}

@Override
public Status convertToEntityAttribute(String dbData) {
return Status.valueOf(dbData.toUpperCase());
}
}


@Convert

Аннотация @Convert применяется к атрибуту сущности для указания конкретного конвертера. Она принимает следующие параметры:

converter (обязательный):
Класс конвертера, который должен быть применен к атрибуту.
Пример: converter = StatusConverter.class.


attributeName (необязательный):
Используется для указания атрибута вложенного объекта (например, в @Embeddable).
По умолчанию: не используется.


Пример использования:
@Entity
public class User {
@Convert(converter = StatusConverter.class)
private Status status;
}


Значения по умолчанию

Если параметр autoApply не указан в @Converter, по умолчанию используется false.
Если параметр attributeName не указан в
@Convert, конвертер применяется к текущему атрибуту.

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

Применение: Конвертеры применяются на этапе маппинга сущности JPA. Они используются при сохранении сущности в базу данных и при загрузке сущности из базы данных.
Инициализация: Конвертеры инициализируются при создании EntityManagerFactory.
Уничтожение: Конвертеры остаются активными до тех пор, пока существует EntityManagerFactory.


Автоматическое применение конвертеров:

Если конвертер аннотирован @Converter(autoApply = true), он автоматически применяется ко всем атрибутам соответствующего типа в сущностях.

#Java #Training #Hard #Spring #SpringDataJPA #Convert #Converter
Кастомизация конвертеров:

Spring Boot позволяет регистрировать конвертеры вручную через конфигурацию EntityManagerFactory.

Пример ручной регистрации конвертера:
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.domain");

HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);

Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
properties.put("hibernate.hbm2ddl.auto", "update");
em.setJpaPropertyMap(properties);

// Регистрация конвертера
em.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
em.getJpaPropertyMap().put("javax.persistence.bean.validation.mode", "none");
em.getJpaPropertyMap().put("hibernate.session_factory.interceptor", new EmptyInterceptor() {
@Override
public void onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
// Логика перехвата
}
});

return em;
}


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

Автоматическое применение:

Используйте @Converter(autoApply = true), если конвертер должен применяться ко всем атрибутам соответствующего типа.

Ручное применение:
Используйте @Convert(converter = MyConverter.class), если конвертер должен применяться только к конкретным атрибутам.

Кастомизация маппинга:
Для сложных сценариев можно использовать @Embeddable и @Embedded в сочетании с конвертерами.

Пример использования @Embeddable:
@Embeddable
public class Address {
private String street;
private String city;

@Convert(converter = ZipCodeConverter.class)
private String zipCode;
}


Использование вложенных объектов:
Конвертеры могут применяться к атрибутам вложенных объектов через параметр attributeName в @Convert.

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

public class Task200325 {
public static void main(String[] args) {
int[] arr = new int[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = arr[0] + arr[1];
arr[3] = arr[2] + arr[1];
arr[4] = arr[3] + arr[2];

System.out.println(arr[4]);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
5%
3
7%
5
81%
8
7%
Exception
1с-ники ну неужто все так плохо? 🤣

https://t.me/Java_for_beginner_dev

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

Какой оператор используется для логического "И"?
Anonymous Quiz
13%
||
85%
&&
0%
!
2%
|
Аннотации @PrePersist и @PostPersist

Аннотации @PrePersist и @PostPersist используются в Java Persistence API (JPA) для указания методов обратного вызова (callback), которые выполняются до и после сохранения сущности в базу данных. Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).

@PrePersist: Метод, аннотированный @PrePersist, вызывается перед тем, как сущность будет сохранена в базу данных (перед выполнением persist).
@PostPersist: Метод, аннотированный @PostPersist, вызывается после того, как сущность была успешно сохранена в базу данных (после выполнения persist).

Эти аннотации полезны для выполнения дополнительной логики, например, инициализации значений, валидации или логирования, до или после сохранения сущности.

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

Аннотации @PrePersist и @PostPersist не принимают параметров. Они применяются к методам сущности, которые должны быть вызваны в соответствующий момент жизненного цикла сущности.

Требования к методам:

Метод должен быть void и не принимать параметров.
Метод может иметь любой модификатор доступа (public, protected, private).
Метод не должен быть статическим.


Пример использования:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@PrePersist
private void beforePersist() {
System.out.println("Before persisting user: " + this.name);
if (this.name == null) {
this.name = "DEFAULT_NAME";
}
}

@PostPersist
private void afterPersist() {
System.out.println("User persisted with ID: " + this.id);
}
}


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

@PrePersist:
Вызывается перед выполнением операции persist в EntityManager.
Используется для инициализации или валидации данных перед сохранением.
Пример: установка значений по умолчанию, генерация UUID, проверка обязательных полей.


@PostPersist:
Вызывается после успешного выполнения операции persist и фиксации транзакции.
Используется для выполнения действий после сохранения, например, логирования или отправки уведомлений.
Пример: логирование ID сохраненной сущности, отправка события в систему сообщений.


Логирование жизненного цикла:

Для отладки можно включить логирование жизненного цикла сущностей через Hibernate:
spring.jpa.properties.hibernate.ejb.event.post-persist=org.hibernate.event.internal.DefaultPersistEventListener


Кастомизация событий:
Если требуется более сложная обработка событий, можно использовать @EntityListeners для определения слушателей сущностей.

Пример использования @EntityListeners:
@Entity
@EntityListeners(UserListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
}

public class UserListener {
@PrePersist
public void beforePersist(User user) {
System.out.println("Before persisting user: " + user.getName());
}

@PostPersist
public void afterPersist(User user) {
System.out.println("User persisted with ID: " + user.getId());
}
}


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

Использование @EntityListeners:
Для разделения логики можно вынести методы обратного вызова в отдельный класс и использовать @EntityListeners.

Глобальные слушатели:
Для применения логики ко всем сущностям можно зарегистрировать глобальный слушатель через Hibernate.

Пример глобального слушателя:
public class GlobalEntityListener {
@PrePersist
public void beforePersist(Object entity) {
System.out.println("Before persisting entity: " + entity.getClass().getSimpleName());
}

@PostPersist
public void afterPersist(Object entity) {
System.out.println("Entity persisted: " + entity.getClass().getSimpleName());
}
}


Регистрация глобального слушателя в Hibernate:
spring.jpa.properties.hibernate.ejb.event.pre-persist=com.example.GlobalEntityListener
spring.jpa.properties.hibernate.ejb.event.post-persist=com.example.GlobalEntityListener


#Java #Training #Hard #Spring #SpringDataJPA #PrePersist #PostPersist
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Аннотации @PreUpdate и @PostUpdate

Аннотации @PreUpdate и @PostUpdate используются в Java Persistence API (JPA) для указания методов обратного вызова (callback), которые выполняются до и после обновления сущности в базе данных. Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).

@PreUpdate: Метод, аннотированный @PreUpdate, вызывается перед тем, как сущность будет обновлена в базе данных (перед выполнением update).
@PostUpdate: Метод, аннотированный @PostUpdate, вызывается после того, как сущность была успешно обновлена в базе данных (после выполнения update).

Эти аннотации полезны для выполнения дополнительной логики, например, валидации, логирования или обновления зависимых данных, до или после обновления сущности.

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

Аннотации @PreUpdate и @PostUpdate не принимают параметров. Они применяются к методам сущности, которые должны быть вызваны в соответствующий момент жизненного цикла сущности.

Требования к методам:
Метод должен быть void и не принимать параметров.
Метод может иметь любой модификатор доступа (public, protected, private).
Метод не должен быть статическим.


Пример использования:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@PreUpdate
private void beforeUpdate() {
System.out.println("Before updating user: " + this.name);
if (this.name == null) {
this.name = "DEFAULT_NAME";
}
}

@PostUpdate
private void afterUpdate() {
System.out.println("User updated with ID: " + this.id);
}
}


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

@PreUpdate:
Вызывается перед выполнением операции update в EntityManager.
Используется для валидации или модификации данных перед обновлением.
Пример: проверка обязательных полей, обновление временных меток.


@PostUpdate:
Вызывается после успешного выполнения операции update и фиксации транзакции.
Используется для выполнения действий после обновления, например, логирования или отправки уведомлений.
Пример: логирование ID обновленной сущности, отправка события в систему сообщений.


Кастомизация событий:
Если требуется более сложная обработка событий, можно использовать @EntityListeners для определения слушателей сущностей.

Пример использования @EntityListeners:
@Entity
@EntityListeners(UserListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
}

public class UserListener {
@PreUpdate
public void beforeUpdate(User user) {
System.out.println("Before updating user: " + user.getName());
}

@PostUpdate
public void afterUpdate(User user) {
System.out.println("User updated with ID: " + user.getId());
}
}


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

Использование в сущности:
Методы @PreUpdate и @PostUpdate можно определить непосредственно в сущности.

Использование @EntityListeners:
Для разделения логики можно вынести методы обратного вызова в отдельный класс и использовать @EntityListeners.

Глобальные слушатели:
Для применения логики ко всем сущностям можно зарегистрировать глобальный слушатель через Hibernate.

Пример глобального слушателя:
public class GlobalEntityListener {
@PreUpdate
public void beforeUpdate(Object entity) {
System.out.println("Before updating entity: " + entity.getClass().getSimpleName());
}

@PostUpdate
public void afterUpdate(Object entity) {
System.out.println("Entity updated: " + entity.getClass().getSimpleName());
}
}


Регистрация глобального слушателя в Hibernate:
spring.jpa.properties.hibernate.ejb.event.pre-update=com.example.GlobalEntityListener
spring.jpa.properties.hibernate.ejb.event.post-update=com.example.GlobalEntityListener


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

abstract class Shape2103 {
abstract void draw();
}

class Circle2103 extends Shape2103 {
void draw() {
System.out.println("Drawing Circle");
}
}

class Square2103 extends Shape2103 {
void draw() {
System.out.println("Drawing Square");
}
}

public class Task210325 {
public static void main(String[] args) {
Shape2103 shape = new Circle2103();
shape.draw();
((Square2103) shape).draw();
}
}


#Tasks
Ну хоть пинка не дал 🤣

https://t.me/Java_for_beginner_dev

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

Какой тип данных используется для хранения одного символа?
Anonymous Quiz
2%
String
2%
int
92%
char
4%
byte
Аннотации @PreRemove и @PostRemove

Аннотации @PreRemove и @PostRemove используются в Java Persistence API (JPA) для указания методов обратного вызова (callback), которые выполняются до и после удаления сущности из базы данных. Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).

@PreRemove: Метод, аннотированный @PreRemove, вызывается перед тем, как сущность будет удалена из базы данных (перед выполнением remove).
@PostRemove: Метод, аннотированный @PostRemove, вызывается после того, как сущность была успешно удалена из базы данных (после выполнения remove).

Эти аннотации полезны для выполнения дополнительной логики, например, очистки зависимых данных, логирования или отправки уведомлений, до или после удаления сущности.

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

Аннотации @PreRemove и @PostRemove не принимают параметров. Они применяются к методам сущности, которые должны быть вызваны в соответствующий момент жизненного цикла сущности.

Требования к методам:
Метод должен быть void и не принимать параметров.
Метод может иметь любой модификатор доступа (public, protected, private).
Метод не должен быть статическим.


Пример использования:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@PreRemove
private void beforeRemove() {
System.out.println("Before removing user: " + this.name);
// Логика перед удалением
}

@PostRemove
private void afterRemove() {
System.out.println("User removed with ID: " + this.id);
// Логика после удаления
}
}


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

@PreRemove:
Вызывается перед выполнением операции remove в EntityManager.
Используется для выполнения действий перед удалением, например, очистки зависимых данных или валидации.
Пример: удаление связанных записей в других таблицах, проверка условий удаления.


@PostRemove:
Вызывается после успешного выполнения операции remove и фиксации транзакции.
Используется для выполнения действий после удаления, например, логирования или отправки уведомлений.
Пример: логирование ID удаленной сущности, отправка события в систему сообщений.


Кастомизация событий:
Если требуется более сложная обработка событий, можно использовать @EntityListeners для определения слушателей сущностей.

Пример использования @EntityListeners:
@Entity
@EntityListeners(UserListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
}

public class UserListener {
@PreRemove
public void beforeRemove(User user) {
System.out.println("Before removing user: " + user.getName());
}

@PostRemove
public void afterRemove(User user) {
System.out.println("User removed with ID: " + user.getId());
}
}


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

Использование в сущности:
Методы @PreRemove и @PostRemove можно определить непосредственно в сущности.

Использование @EntityListeners:
Для разделения логики можно вынести методы обратного вызова в отдельный класс и использовать @EntityListeners.

Глобальные слушатели:
Для применения логики ко всем сущностям можно зарегистрировать глобальный слушатель через Hibernate.

Пример глобального слушателя:
public class GlobalEntityListener {
@PreRemove
public void beforeRemove(Object entity) {
System.out.println("Before removing entity: " + entity.getClass().getSimpleName());
}

@PostRemove
public void afterRemove(Object entity) {
System.out.println("Entity removed: " + entity.getClass().getSimpleName());
}
}


Регистрация глобального слушателя в Hibernate:
spring.jpa.properties.hibernate.ejb.event.pre-remove=com.example.GlobalEntityListener
spring.jpa.properties.hibernate.ejb.event.post-remove=com.example.GlobalEntityListener


#Java #Training #Hard #Spring #SpringDataJPA #PreRemove #PostRemove
Всем доброе утро! ☀️

Мы дожили до очередных выходных, что не может не радовать🤪
Наряженная рабочая неделя окончена и можно расслабиться
...

Завтра встречу организуем, но тему еще не придумал))) Думаю что-то сообразим✌️

Пишите как Вы проводите выходные?
👀

А всем остальным - просто хороших выходных! 🍻
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