Java for Beginner
673 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
This media is not supported in your browser
VIEW IN TELEGRAM
Ну раз никто ничего не предлагает, сегодня отдохнем. ✌️

А вот пока Вам смешной мем😜

#Mems
Введение в ORM и Spring Data JPA

ORM (Object-Relational Mapping) — это технология, которая позволяет разработчикам работать с базами данных на уровне объектов, а не на уровне SQL-запросов. Основная идея заключается в том, чтобы "связать" объектно-ориентированную модель приложения с реляционной моделью базы данных.

Примеры популярных ORM-фреймворков:
Hibernate
JPA (Java Persistence API)


Spring Data JPA — это часть экосистемы Spring, которая предоставляет инструменты для работы с базами данных на основе спецификации JPA. Она упрощает создание репозиториев и выполнение стандартных операций с данными (CRUD).

Преимущества Spring Data JPA:

Упрощение разработки: вам не нужно писать стандартные SQL-запросы.
Автоматическая реализация методов репозиториев: интерфейсы обрабатываются динамически.
Поддержка сложных запросов: с использованием методов
@Query или Criteria API.

Основные компоненты Spring Data JPA

1. EntityManager
Это основной интерфейс для работы с JPA, который управляет состоянием объектов и их отображением в базу данных. С помощью него можно выполнять CRUD-операции и управлять транзакциями.

2. Репозитории
В Spring Data JPA используются интерфейсы репозиториев, которые помогают выполнять операции с базой данных.

CrudRepository — базовый интерфейс для CRUD операций.
JpaRepository — расширяет CrudRepository, добавляя дополнительные возможности.


Подключение Spring Data JPA

Добавьте в файл application.properties или application.yml параметры подключения:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update


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

Создадим простое приложение для управления данными о пользователях.

1. Модель данных
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
private String email;

// Getters and Setters
}


2. Репозиторий
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}


3. Сервисный слой
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class UserService {

private final UserRepository userRepository;

public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}

public List<User> getAllUsers() {
return userRepository.findAll();
}

public User saveUser(User user) {
return userRepository.save(user);
}
}


4. Контроллер
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {

private final UserService userService;

public UserController(UserService userService) {
this.userService = userService;
}

@GetMapping
public List<User> getUsers() {
return userService.getAllUsers();
}

@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
}


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

public class Task181124_1 {
public static void main(String[] args) {
int result = 0;
for (int i = 0; i < 3; i++) { // Внешний цикл
for (int j = i; j < 3; j++) { // Внутренний цикл
result += i + j;
}
}
System.out.println(result);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
68%
12
5%
15
16%
18
11%
22
"А еще у них код грязный, потому что не моются месяцами" 🤪😂😂😂

https://t.me/Java_for_beginner_dev

#Mems
Основные аннотации JPA: @Entity, @Table, @Id

1. Аннотация @Entity
@Entity указывает, что класс представляет собой сущность базы данных. Каждая сущность соответствует таблице в базе данных.

Пример:
import jakarta.persistence.Entity;

@Entity
public class Product {
private Long id;
private String name;
private Double price;
}
Если класс помечен как @Entity, но таблица не указана явно, Spring автоматически использует название класса для создания таблицы в базе данных.


2. Аннотация @Table

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

Пример:
import jakarta.persistence.Entity;
import jakarta.persistence.Table;

@Entity
@Table(name = "products", schema = "shop")
public class Product {
private Long id;
private String name;
private Double price;
}
Если имя таблицы не указано, то по умолчанию используется имя класса.


3. Аннотация @Id

@Id используется для указания первичного ключа таблицы.

Пример:
import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class Product {

@Id
private Long id;

private String name;
private Double price;
}


Другие полезные аннотации

1.
@GeneratedValue

Используется вместе с @Id для автоматической генерации значения первичного ключа.
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


Стратегии генерации:
AUTO — автоматически выбирает стратегию, зависящую от базы данных.
IDENTITY — использует автоинкремент в базе данных.
SEQUENCE — использует специальную таблицу для генерации уникальных значений.
TABLE — сохраняет последовательности значений в отдельной таблице.


2. @Column

Позволяет указать имя столбца, его уникальность, длину и другие параметры.
import jakarta.persistence.Column;

@Column(name = "product_name", nullable = false, unique = true)
private String name;


3. @Transient

Позволяет исключить поле из отображения в базе данных.
@Transient
private String tempData;


Пример полной конфигурации
import jakarta.persistence.*;

@Entity
@Table(name = "products")
public class Product {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "product_name", nullable = false)
private String name;

private Double price;

@Transient
private String tempData;

// Getters and Setters
}


#Java #Training #Spring #Entity #Table #Id #GeneratedValue #Column #Transient
Аннотации JPA для полей: @Column, @GeneratedValue, @ManyToOne

1. Аннотация @Column

Аннотация @Column используется для настройки маппинга поля сущности на столбец таблицы базы данных. С её помощью можно задать имя столбца, его длину, уникальность, возможность быть NULL и другие атрибуты.

Основные параметры:
name — имя столбца в базе данных.
nullable — допускает ли столбец значение NULL.
unique — устанавливает, должны ли значения в столбце быть уникальными.
length — длина для столбцов типа VARCHAR.
columnDefinition — SQL-выражение для явного указания типа столбца.


Пример использования:
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class User {

@Id
private Long id;

@Column(name = "username", nullable = false, unique = true, length = 50)
private String username;

@Column(name = "email", nullable = false, unique = true)
private String email;

@Column(name = "age", columnDefinition = "INTEGER DEFAULT 18")
private int age;

// Геттеры и сеттеры
}


В этом примере мы видим, что:
Поле username будет связано со столбцом username, не допускающим NULL и с максимальной длиной 50 символов.
Поле age связано со столбцом с SQL-типом INTEGER, по умолчанию равным 18.


2. Аннотация @GeneratedValue

Аннотация @GeneratedValue используется для указания стратегии генерации значений первичного ключа. Она применима к полям, помеченным как @Id.

Основные стратегии:
AUTO — выбор стратегии определяется провайдером JPA.
IDENTITY — генерация значения средствами базы данных.
SEQUENCE — использование последовательности, определенной в базе данных.
TABLE — использование таблицы для хранения значений идентификаторов.


Пример использования:
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Product {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

private double price;

// Геттеры и сеттеры
}
Здесь id будет автоматически генерироваться базой данных.


3. Аннотация @ManyToOne

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

Пример использования:
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;

@Entity
public class Order {

@Id
private Long id;

private String description;

@ManyToOne
private Customer customer;

// Геттеры и сеттеры
}
Эта аннотация указывает, что множество заказов (Order) могут быть связаны с одним клиентом (Customer).


#Java #Training #Spring #Column #GeneratedValue #ManyToOne
Недавнее обсуждение многопоточности в нашем чате, подтолкнуло меня восполнить недостатки знаний в этой области Java. 🧐

Дополняю темы про распространенные ошибки многопоточности.

Распространенные ошибки многопоточности

Race Condition (Состояние гонки)

Race Condition — это ситуация, когда поведение программы зависит от порядка или своевременности выполнения потоков. Оно возникает, когда несколько потоков одновременно обращаются к одному и тому же ресурсу (например, переменной или объекту), и хотя бы один из них изменяет его.

Пример Race Condition:
public class Counter {
private int count = 0;

public void increment() {
count++; // Неатомарная операция: чтение, увеличение, запись
}

public int getCount() {
return count;
}
}

public class RaceConditionExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();

Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});

Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});

t1.start();
t2.start();
t1.join();
t2.join();

System.out.println("Final count: " + counter.getCount()); // Ожидаем 2000, но результат может быть меньше
}
}


Почему Race Condition?

count++ не является атомарной операцией.

Она состоит из трех шагов:
Чтение текущего значения count.
Увеличение значения.
Запись нового значения обратно в переменную.


Если оба потока прочитают одно и то же значение до записи, итоговое значение будет некорректным.

Deadlock (Взаимная блокировка)

Deadlock — ситуация, при которой два или более потоков блокируют друг друга, ожидая освобождения ресурсов.

Пример Deadlock:
public class DeadlockExample {

private final Object lock1 = new Object();
private final Object lock2 = new Object();

public void method1() {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock1...");
try { Thread.sleep(50); } catch (InterruptedException e) {}

synchronized (lock2) {
System.out.println("Thread 1: Acquired lock2.");
}
}
}

public void method2() {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock2...");
try { Thread.sleep(50); } catch (InterruptedException e) {}

synchronized (lock1) {
System.out.println("Thread 2: Acquired lock1.");
}
}
}

public static void main(String[] args) {
DeadlockExample demo = new DeadlockExample();

Thread t1 = new Thread(demo::method1);
Thread t2 = new Thread(demo::method2);

t1.start();
t2.start();
}
}


Что происходит:
Поток 1 захватывает lock1 и ждет lock2.
Поток 2 захватывает lock2 и ждет lock1.
Оба потока застревают, ожидая освобождения ресурсов друг от друга.


#Java #Training #Multithreading #Medium #Race_Condition #Livelock #Starvation #Thread_Interference #Memory_Consistency_Errors #Multithreading_errors
Livelock (Живая блокировка)

Livelock похож на Deadlock, но здесь потоки не блокируются, а продолжают изменять свое состояние в попытке избежать конфликта, не продвигаясь дальше.

Пример Livelock:

public class LivelockExample {

static class Worker {
private boolean active = true;

public synchronized void work(Worker other) {
while (active) {
System.out.println(Thread.currentThread().getName() + " is working...");
try { Thread.sleep(50); } catch (InterruptedException e) {}

if (other.isActive()) {
System.out.println(Thread.currentThread().getName() + " is waiting...");
continue;
}
break;
}
}

public synchronized void setActive(boolean active) {
this.active = active;
}

public synchronized boolean isActive() {
return active;
}
}

public static void main(String[] args) {
Worker w1 = new Worker();
Worker w2 = new Worker();

Thread t1 = new Thread(() -> w1.work(w2), "Worker 1");
Thread t2 = new Thread(() -> w2.work(w1), "Worker 2");

t1.start();
t2.start();
}
}


Что происходит:
Оба потока продолжают "уступать" друг другу, не завершив работу.

Starvation (Голодание)

Starvation — ситуация, когда поток постоянно лишается доступа к ресурсу из-за того, что другие потоки с более высоким приоритетом занимают его.

Причина: Использование приоритетов потоков, где высокоприоритетные потоки блокируют низкоприоритетные.

Thread Interference (Конфликт потоков)

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

Пример:
Потоки выполняют операции на одной переменной без синхронизации, что приводит к некорректным итоговым значениям.

Memory Consistency Errors (Ошибки согласованности памяти)

Эти ошибки возникают, когда один поток изменяет данные, но другие потоки видят устаревшее состояние этих данных.

Причина: Использование кэша процессора.
Переменная, измененная в одном потоке, может не быть видимой для других потоков.

Решение:
Использование volatile для обеспечения видимости изменений.
private static volatile boolean running = true;

public void run() {
while (running) {
// Выполняем задачу
}
}


Как предотвратить ошибки многопоточности

Использование синхронизации:
synchronized блоки или методы.
ReentrantLock для более гибкого управления блокировкой.


Использование атомарных типов:
Классы из пакета java.util.concurrent.atomic:
AtomicInteger, AtomicBoolean, AtomicReference.


Использование высокоуровневых утилит:
ExecutorService для управления потоками.
CountDownLatch, Semaphore, CyclicBarrier.


Избегание Deadlock:
Всегда захватывать блокировки в одном и том же порядке.
Использование таймаутов при ожидании захвата.


Проверка и отладка:
Инструменты отладки (например, jstack, VisualVM) для анализа состояния потоков.
Логирование текущих блокировок и их владельцев.


#Java #Training #Multithreading #Medium #Race_Condition #Livelock #Starvation #Thread_Interference #Memory_Consistency_Errors #Multithreading_errors
Что выведет код?

class Parent { }

class Child extends Parent { }

public class Task191124_1 {
public static void main(String[] args) {
Parent obj1 = new Parent();
Parent obj2 = new Child();
Child obj3 = new Child();

System.out.println(obj1 instanceof Parent);
System.out.println(obj2 instanceof Child);
System.out.println(obj3 instanceof Parent);
System.out.println(obj1 instanceof Child);
}
}


#Tasks
И это за три часа в день?😱🤪😂

https://t.me/Java_for_beginner_dev

#Mems
Аннотации JPA: @OneToOne, @ManyToMany, @JoinColumn, @Lob, @Query, @Modifying, @EnableJpaRepositories

1. @OneToOne

Аннотация @OneToOne используется для определения связи "один к одному" между сущностями. Это может быть, например, связь между пользователем и его профилем.

@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne
@JoinColumn(name = "profile_id", referencedColumnName = "id")
private Profile profile;
}

@Entity
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String bio;
}
Здесь связь между User и Profile устанавливается через внешний ключ profile_id.


2. @ManyToMany

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

@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List<Course> courses;
}

@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;

@ManyToMany(mappedBy = "courses")
private List<Student> students;
}
Связь осуществляется через промежуточную таблицу student_course.


3. @JoinColumn

Аннотация
@JoinColumn задаёт внешний ключ для связи. Она может использоваться с аннотациями @OneToOne и @ManyToOne.
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne
@JoinColumn(name = "customer_id", nullable = false)
private Customer customer;
}
Здесь customer_id в таблице Order будет внешним ключом, ссылающимся на таблицу Customer.


4. @Lob

@Lob используется для маппинга больших объектов, таких как текстовые или бинарные данные.
@Entity
public class Document {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Lob
private String content; // Для больших текстов

@Lob
private byte[] fileData; // Для бинарных данных
}


5.
@Query

Аннотация @Query позволяет задавать JPQL или SQL-запросы прямо в репозитории.
public interface UserRepository extends JpaRepository<User, Long> {

@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
}


6. @Modifying

Используется вместе с
@Query для выполнения операций обновления или удаления данных.
public interface UserRepository extends JpaRepository<User, Long> {

@Modifying
@Query("UPDATE User u SET u.name = :name WHERE u.id = :id")
void updateUserName(@Param("id") Long id, @Param("name") String name);
}


7. @EnableJpaRepositories

Эта аннотация активирует JPA-репозитории в Spring Boot.
@Configuration
@EnableJpaRepositories(basePackages = "com.example.repository")
public class AppConfig {
}


#Java #Training #Spring #OneToOne #ManyToMany #JoinColumn #Lob #Query #Modifying #EnableJpaRepositories
Аннотации JPA: @Embeddable, @Embedded, @ElementCollection, @Inheritance, @Cacheable, @Lock, @EntityListeners, @SQLInsert, @SQLUpdate, @SQLDelete

1. @Embeddable и @Embedded

Аннотация
@Embeddable обозначает класс, который будет встраиваться в другие сущности, а @Embedded — указывает, что поле встраивает такой класс.
@Embeddable
public class Address {
private String street;
private String city;
}

@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Embedded
private Address address;
}


2. @ElementCollection

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

@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ElementCollection
private List<String> tags;
}


3.
@Inheritance

Настраивает стратегию наследования для сущностей.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Vehicle {
@Id
private Long id;
}

@Entity
public class Car extends Vehicle {
private int seatingCapacity;
}


4. @Cacheable

Обозначает, что сущность может быть закеширована.
@Entity
@Cacheable
public class Product {
@Id
private Long id;
private String name;
}


5. @Lock

Используется для управления блокировками данных.

@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT u FROM User u WHERE u.id = :id")
User findForUpdate(@Param("id") Long id);


6.
@EntityListeners

Позволяет подключать слушатели для отслеживания событий сущности.

@Entity
@EntityListeners(AuditListener.class)
public class Order {
@Id
private Long id;
}


7.
@SQLInsert, @SQLUpdate, @SQLDelete

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

@SQLInsert(sql = "INSERT INTO user_audit (id, username) VALUES (?, ?)")
@SQLDelete(sql = "DELETE FROM user_audit WHERE id = ?")
@Entity
public class UserAudit {
@Id
private Long id;
}


#Java #Training #Spring #Embeddable, #Embedded, #ElementCollection, #Inheritance, #Cacheable, #Lock, #EntityListeners, #SQLInsert, #SQLUpdate, #SQLDelete
Что выведет код?

import java.math.BigDecimal;

public class Task201124_1 {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("3");
BigDecimal num2 = new BigDecimal("2");

BigDecimal sum = num1.add(num2);
BigDecimal product = num1.multiply(num2);

BigDecimal result = sum.subtract(product).divide(new BigDecimal("1.0"), 10, BigDecimal.ROUND_HALF_UP);

System.out.println(result);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
29%
1
0%
2.0
14%
5.0
57%
-1.0
Кто вакансии искал?😂😂😂

https://t.me/Java_for_beginner_dev

#Mems
Сущности в JPA

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

1. Основные принципы сущности в JPA

Сущности JPA — это классы, которые автоматически маппируются на таблицы базы данных.

Важно понимать, что сущности:

Являются Java POJO (Plain Old Java Object) классами, которые должны иметь конструктор без параметров.
Должны быть аннотированы аннотацией
@Entity.
Каждый объект сущности будет соответствовать одной строке в базе данных.
Для работы с сущностью в базе данных используется Entity Manager, который управляет состоянием объектов и их персистенцией.


2. Основные аннотации для сущностей

2.1 @Entity
Аннотация @Entity указывает, что класс является сущностью, которая будет маппироваться на таблицу в базе данных.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

private String email;

// геттеры и сеттеры
}


Класс, аннотированный @Entity, будет автоматически сопоставлен с таблицей в базе данных.
Если не указано, имя таблицы будет автоматически сформировано из имени класса.


2.2 @Table

Аннотация @Table используется для настройки таблицы, с которой будет работать сущность. Вы можете указать имя таблицы, схему и ограничения.
@Entity
@Table(name = "users", schema = "public")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

private String email;
}
Атрибуты name и schema позволяют указать, на какую таблицу и в какой схеме будет маппироваться класс.


2.3 @Id

Аннотация @Id указывает на поле, которое является первичным ключом для сущности.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Поле, помеченное @Id, будет использоваться как первичный ключ таблицы.
Аннотация @GeneratedValue указывает стратегию генерации значений первичного ключа.


3. Стратегии генерации значений для первичного ключа

3.1 GenerationType.IDENTITY


Эта стратегия используется для автоматической генерации значений в столбце, обычно используется в базе данных с поддержкой автоинкремента.
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


3.2 GenerationType.SEQUENCE


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

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
@SequenceGenerator(name = "user_seq", sequenceName = "user_sequence")
private Long id;


3.3 GenerationType.TABLE

Использует специальную таблицу для генерации уникальных значений.
@GeneratedValue(strategy = GenerationType.TABLE, generator = "id_gen")
@TableGenerator(name = "id_gen", table = "id_generator")
private Long id;


4. Маппинг полей сущности на столбцы таблицы

4.1
@Column

Аннотация @Column используется для маппинга поля сущности на столбец таблицы.
@Column(name = "username", nullable = false, unique = true, length = 50)
private String username;
name: имя столбца.
nullable: указывает, может ли столбец быть пустым.
unique: задает уникальность значения столбца.
length: максимальная длина строкового значения.


4.2 @Lob

Аннотация @Lob используется для хранения больших объектов (например, текста или бинарных данных). Это может быть полезно для хранения изображений, файлов или больших текстовых полей.

@Lob
private String description;


4.3 @Transient

Аннотация
@Transient используется для исключения поля из маппинга. Это поле не будет сохраняться в базе данных.
@Transient
private String temporaryData;


#Java #Training #Spring #JPA_Entity
5. Работа с жизненным циклом сущности

5.1 @PrePersist, @PostPersist

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

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

@PrePersist
public void prePersist() {
System.out.println("Before persisting the Order");
}

@PostPersist
public void postPersist() {
System.out.println("After persisting the Order");
}
}


#Java #Training #Spring #JPA_Entity
Репозитории в Spring Data: интерфейс CrudRepository и JpaRepository

В экосистеме Spring Data важнейшую роль играют репозитории, которые позволяют работать с данными, не пиша сложного SQL-кода. Два ключевых интерфейса, которые используются чаще всего, — это CrudRepository и JpaRepository.

CrudRepository

CrudRepository — это базовый интерфейс для работы с CRUD-операциями (Create, Read, Update, Delete). Он предоставляет набор стандартных методов, которые можно использовать для управления сущностями.

Основные методы CrudRepository:
save(S entity): Сохраняет сущность.
findById(ID id): Находит сущность по ID.
existsById(ID id): Проверяет существование сущности с заданным ID.
findAll(): Возвращает все сущности.
deleteById(ID id): Удаляет сущность по ID.
deleteAll(): Удаляет все сущности.


Пример использования CrudRepository:
import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository<User, Long> {
}
В этом примере UserRepository предоставляет все стандартные CRUD-операции для работы с сущностью User.


JpaRepository

JpaRepository расширяет возможности CrudRepository и добавляет дополнительные методы для работы с коллекциями и пагинацией. Этот интерфейс является частью Spring Data JPA и более мощным инструментом.

Основные методы JpaRepository:
saveAll(Iterable<S> entities): Сохраняет коллекцию сущностей.
findAll(Sort sort): Возвращает все сущности с сортировкой.
findAll(Pageable pageable): Возвращает сущности с постраничной разбивкой.
flush(): Принудительно записывает изменения в базу данных.
saveAndFlush(S entity): Сохраняет сущность и немедленно записывает изменения.


Пример использования JpaRepository:
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long> {
}


Теперь можно использовать более сложные запросы, такие как сортировка и пагинация:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

@Autowired
private ProductRepository productRepository;

public Page<Product> getProducts(int page, int size) {
return productRepository.findAll(PageRequest.of(page, size));
}
}


Основные отличия CrudRepository и JpaRepository:

JpaRepository предоставляет больше методов, что полезно для сложных операций.
CrudRepository минималистичен, подходит для простых операций CRUD.
JpaRepository работает на базе JPA, добавляя функциональность для сортировки и пагинации.
Использование JpaRepository предпочтительно, если проект использует JPA и предполагает расширенные функции.


Пример работы с JpaRepository

Предположим, у нас есть сущность Order:
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

@Entity
public class Order {
@Id
@GeneratedValue
private Long id;
private String description;
private double price;

// getters and setters
}


Теперь создадим репозиторий:
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderRepository extends JpaRepository<Order, Long> {
}


Мы можем легко сохранять и получать данные:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

@Autowired
private OrderRepository orderRepository;

public Order saveOrder(Order order) {
return orderRepository.save(order);
}

public List<Order> getAllOrders() {
return orderRepository.findAll();
}
}


#Java #Training #Spring #CrudRepository #JpaRepository
Продолжаем устранять пробелы в многопоточке Java. Сегодня рассмотрим интерфейс Callable.

Callable

Callable — это функциональный интерфейс в Java, который представляет задачу, выполняемую в отдельном потоке. Он был введен в Java 5 вместе с пакетами для многозадачности (java.util.concurrent), и его основное назначение — предоставить способ выполнения асинхронных операций, которые могут вернуть результат.


1. Основные особенности Callable


Интерфейс Callable аналогичен интерфейсу Runnable, но с двумя важными отличиями:
Возвращаемое значение: В отличие от Runnable, который не возвращает значения (void run()), метод call() интерфейса Callable может возвращать результат. Это позволяет возвращать какие-либо данные (например, результат вычислений или ошибку).
Исключения: Метод call() может бросать исключения, в отличие от метода run() интерфейса Runnable, который не может выбрасывать проверяемые исключения.
Возвращаемое значение: Метод call() возвращает объект типа V (генерик), который может быть любым типом. Это возвращаемое значение удобно для получения результатов выполнения асинхронных задач.


Использование с ExecutorService:
Задачи, реализующие Callable, часто выполняются через ExecutorService, который предоставляет методы для асинхронного выполнения таких задач.

2. Методы интерфейса Callable

call() — это основной метод интерфейса. Он выполняет задачу и возвращает результат типа V. Также этот метод может выбрасывать проверяемые исключения (Exception), что отличает его от метода run() интерфейса Runnable, который не может этого делать.
public interface Callable<V> {
V call() throws Exception;
}


3. Основные классы и интерфейсы для работы с Callable

Чтобы эффективно использовать интерфейс Callable, в Java существует несколько классов и интерфейсов для работы с многозадачностью:
ExecutorService — интерфейс для управления пулом потоков и выполнения задач в асинхронном режиме.
Future<V> — интерфейс, который представляет результат асинхронной задачи. Он используется для получения результата выполнения Callable после завершения его работы. Через объект Future можно проверить статус выполнения задачи, отменить её или получить результат (если задача завершена).


Пример использования Callable и ExecutorService:
import java.util.concurrent.*;

public class CallableExample {
public static void main(String[] args) {
// Создаем ExecutorService с пулом потоков
ExecutorService executor = Executors.newFixedThreadPool(2);

// Задача, которая возвращает результат
Callable<Integer> task = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
// Пример вычислений
return 123;
}
};

// Выполняем задачу и получаем объект Future
Future<Integer> future = executor.submit(task);

try {
// Получаем результат выполнения задачи
Integer result = future.get(); // блокирует текущий поток до получения результата
System.out.println("Результат: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}


4. Методы интерфейса Future

Объект Future, который возвращается методом submit() объекта ExecutorService, предоставляет несколько полезных методов для работы с результатом асинхронной задачи:
get(): Блокирует текущий поток до получения результата выполнения задачи. Если задача завершена с ошибкой, этот метод выбрасывает ExecutionException.
get(long timeout, TimeUnit unit): Блокирует текущий поток до получения результата или до истечения времени ожидания.
cancel(boolean mayInterruptIfRunning): Отменяет задачу. Если задача не начала выполнение, она будет отменена. Если она уже выполняется, её можно прервать, если указан параметр mayInterruptIfRunning = true.
isCancelled(): Проверяет, была ли задача отменена.
isDone(): Проверяет, завершена ли задача (независимо от того, успешно ли она завершилась).


#Java #Training #Multithreading #Callable