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
Создание методов для поиска данных в Spring Data JPA

Spring Data JPA позволяет разработчикам создавать методы для поиска данных без написания SQL-запросов. Это достигается благодаря методам запроса на основе имен и JPQL-запросам.

Методы поиска по имени

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

Примеры методов поиска:
findBy — находит по полю.
findBy...And... — находит по нескольким полям.
findBy...Or... — находит по одному из нескольких полей.


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

@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private String email;

// getters and setters
}


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

import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByName(String name);
User findByEmail(String email);
List<User> findByNameAndEmail(String name, String email);
}


Использование этих методов:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

@Autowired
private UserRepository userRepository;

public List<User> getUsersByName(String name) {
return userRepository.findByName(name);
}

public User getUserByEmail(String email) {
return userRepository.findByEmail(email);
}

public List<User> getUsersByNameAndEmail(String name, String email) {
return userRepository.findByNameAndEmail(name, email);
}
}


Методы с использованием JPQL

JPQL (Java Persistence Query Language) — это язык запросов, похожий на SQL, но использующий сущности вместо таблиц. В Spring Data JPA вы можете использовать JPQL-запросы с аннотацией @Query.

Добавим метод с JPQL-запросом в UserRepository:
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {

@Query("SELECT u FROM User u WHERE u.name = :name")
List<User> findUsersByName(@Param("name") String name);

@Query("SELECT u FROM User u WHERE u.email LIKE %:emailDomain")
List<User> findUsersByEmailDomain(@Param("emailDomain") String emailDomain);
}


Теперь мы можем использовать эти методы для более гибкого поиска:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

@Autowired
private UserRepository userRepository;

public List<User> findUsersByEmailDomain(String domain) {
return userRepository.findUsersByEmailDomain(domain);
}
}


Сортировка и пагинация

Spring Data JPA позволяет легко добавлять сортировку и пагинацию к любым методам поиска.

Пример с использованием сортировки:
import org.springframework.data.domain.Sort;

List<User> findAll(Sort sort);

List<User> usersSortedByName = userRepository.findAll(Sort.by("name"));


Пример с пагинацией:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;

Page<User> findAll(PageRequest pageable);

Page<User> usersPage = userRepository.findAll(PageRequest.of(0, 10));


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

Задача по Spring JDBC, JPQL, @JpaRepository, @Entity, @Table, @Id создание и выполнение CRUD операций в Spring. Сложность легкая.

Подробный разбор через 30 минут!🫡

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import java.util.List;

@SpringBootApplication
public class Main211124_2 {
public static void main(String[] args) {
SpringApplication.run(Main211124_2.class, args);
}

@Bean
public CommandLineRunner demo(UserRepository2111 repository) {
return args -> {
repository.save(new User2111("Alice", 30));
repository.save(new User2111("Bob", 25));
List<User2111> users = repository.findByAgeGreaterThan(20);
users.forEach(user -> System.out.println(user.getName()));
};
}
}

@Entity
@Table(name = "users2111")
class User2111 {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private int age;

// Конструкторы, геттеры и сеттеры
public User2111() {}

public User2111(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}
}

@Repository
interface UserRepository2111 extends JpaRepository<User2111, Long> {
List<User2111> findByAgeGreaterThan(int age);
}


#TasksSpring
Подробный разбор решения задачи Task211124_2

1. Контекст задачи:

Задача демонстрирует использование Spring Data JPA для работы с базой данных. В частности, она показывает, как использовать аннотации JPA (@Entity, @Table, @Id) для определения сущностей, а также JpaRepository для выполнения CRUD операций и запросов с использованием JPQL. Основное внимание уделяется выполнению операций сохранения и выборки данных.

2. Ключевые элементы кода:

Аннотация @SpringBootApplication:
Указывает, что класс Main211124_2 является главным классом Spring Boot приложения. Она включает в себя @Configuration, @EnableAutoConfiguration, и @ComponentScan, что автоматически настраивает компоненты Spring, включая Spring Data JPA.

Аннотация @Entity:
Класс User2111 помечен аннотацией @Entity, что указывает JPA, что этот класс соответствует таблице в базе данных. Он представляет собой сущность, с которой будет работать JPA.
Аннотация
@Table(name = "users2111"):
Определяет, что эта сущность будет сопоставлена с таблицей users2111 в базе данных. Если аннотация @Table не указана, JPA по умолчанию использует имя класса как имя таблицы.

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

Интерфейс UserRepository2111 и аннотация @Repository:
UserRepository2111 расширяет JpaRepository, что предоставляет стандартные методы CRUD (например, save, findAll, deleteById).
Метод findByAgeGreaterThan(int age) позволяет выполнять JPQL-запрос для получения всех пользователей, у которых возраст больше заданного.


Использование CommandLineRunner:
CommandLineRunner используется для выполнения кода сразу после запуска приложения. В данном случае он выполняет следующие шаги:
Сохраняет в базу данных двух пользователей: "Alice" с возрастом 30 и "Bob" с возрастом 25.
Выполняет запрос findByAgeGreaterThan(20), возвращающий всех пользователей с возрастом больше 20.
Выводит имена выбранных пользователей в консоль.


3. Сценарий работы программы:

Запуск приложения:
Программа запускается с помощью SpringApplication.run(Main211124_2.class, args);. Spring Boot настраивает подключение к базе данных и компоненты Spring Data JPA.

Вставка данных:
Метод save() из JpaRepository используется для сохранения двух записей:
User2111("Alice", 30)
User2111("Bob", 25)


Выполнение запроса:
Метод findByAgeGreaterThan(20) выбирает всех пользователей, у которых возраст больше 20. Это JPQL-запрос, автоматически формируемый Spring Data JPA на основе имени метода.

Вывод данных:
Полученные записи проходят через метод forEach, который вызывает System.out.println для вывода имен в консоль.

4. Ключевые моменты и выводы:

Использование JPA и Spring Data:

Spring Data JPA значительно упрощает работу с базой данных, предоставляя готовые методы для выполнения CRUD операций и поддерживая создание запросов на основе имен методов.

Аннотации JPA:
@Entity и @Table используются для связывания класса с таблицей в базе данных.
@Id и
@GeneratedValue обеспечивают автоматическую генерацию уникальных идентификаторов для каждой записи.

JPQL-запросы и JpaRepository:
Метод findByAgeGreaterThan демонстрирует, как можно выполнять запросы к базе данных, просто определяя метод с соответствующим именем в репозитории.

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

#Solution_TasksSpring
Транзакции в Spring

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

Транзакция — это последовательность операций, которые выполняются как единое целое. Если хотя бы одна из операций в транзакции завершается с ошибкой, все изменения, сделанные в рамках этой транзакции, откатываются.

Ключевые свойства транзакций определяются через ACID:
Atomicity (Атомарность): Все операции в транзакции выполняются или ни одна из них.
Consistency (Согласованность): Транзакция переводит базу данных из одного согласованного состояния в другое.
Isolation (Изолированность): Операции в транзакции не видимы другим транзакциям, пока они не завершатся.
Durability (Устойчивость): После успешного завершения транзакции изменения остаются сохраненными в базе данных, даже в случае сбоя системы.


Пример транзакции в SQL

Предположим, у нас есть две таблицы: accounts и transactions. Нам нужно перевести деньги с одного счета на другой.
BEGIN TRANSACTION;

UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;

INSERT INTO transactions (from_account, to_account, amount) VALUES (1, 2, 100);

COMMIT;
Если любая из этих операций не выполняется, все изменения откатываются.


Транзакции в Spring

Spring обеспечивает управление транзакциями с помощью своих инструментов.

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


Программное управление транзакциями

Для ручного управления транзакциями в Spring используется PlatformTransactionManager.

Пример:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Service
public class TransactionalService {

@Autowired
private PlatformTransactionManager transactionManager;

public void performTransactionalOperation() {
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);

try {
// Ваши операции с базой данных
performDatabaseOperation1();
performDatabaseOperation2();

// Подтверждение транзакции
transactionManager.commit(status);
} catch (Exception e) {
// Откат транзакции в случае ошибки
transactionManager.rollback(status);
throw e;
}
}

private void performDatabaseOperation1() {
// Код операции 1
}

private void performDatabaseOperation2() {
// Код операции 2
}
}
Этот метод предоставляет полный контроль над транзакциями, но делает код более сложным.


Декларативное управление транзакциями

Более простой и популярный способ — это использование аннотации @Transactional.

Преимущества транзакций:

Целостность данных: Транзакции гарантируют, что данные останутся в корректном состоянии.
Стабильность системы: Операции либо полностью завершаются, либо полностью откатываются.
Упрощение отладки: Вы можете быть уверены, что в случае сбоя данные не будут повреждены.


#Java #Training #Spring #Transactions #ACID
Продолжаем устранять пробелы в многопоточке Java. Сегодня рассмотрим Semaphore и CountDownLatch.

Semaphore

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

Основные методы Semaphore

acquire(): Захватывает разрешение (пермит). Если разрешений нет, поток блокируется до тех пор, пока одно из них не станет доступным.
acquire(int permits): Захватывает указанное количество разрешений. Если их недостаточно, поток блокируется.
release(): Освобождает разрешение, увеличивая количество доступных разрешений на 1.
release(int permits): Освобождает указанное количество разрешений.
availablePermits(): Возвращает количество доступных разрешений.
tryAcquire(): Пытается захватить разрешение. Возвращает true, если удалось получить разрешение, иначе false.
tryAcquire(int permits, long timeout, TimeUnit unit): Пытается получить разрешения с указанным временем ожидания.
isFair(): Проверяет, использует ли семафор справедливый порядок захвата разрешений (FIFO).


Типы Semaphore

Несправедливый (non-fair): Потоки получают доступ в произвольном порядке (по умолчанию).
Справедливый (fair): Потоки получают доступ в порядке очереди (FIFO).


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

public class SemaphoreExample {
public static void main(String[] args) {
// Семафор с 2 разрешениями
Semaphore semaphore = new Semaphore(2);

// Пул из 5 потоков
ExecutorService executor = Executors.newFixedThreadPool(5);

for (int i = 0; i < 5; i++) {
final int threadId = i;
executor.submit(() -> {
try {
System.out.println("Thread " + threadId + " is waiting for permit...");
semaphore.acquire(); // Получаем разрешение
System.out.println("Thread " + threadId + " acquired permit.");
Thread.sleep(2000); // Имитируем использование ресурса
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println("Thread " + threadId + " released permit.");
semaphore.release(); // Освобождаем разрешение
}
});
}

executor.shutdown();
}
}


Результат:
В каждый момент времени только 2 потока выполняют свою работу.
Остальные ждут освобождения разрешения.


Нюансы Semaphore

Справедливость (fair vs non-fair):
Несправедливый семафор быстрее, но поток может быть отложен, даже если он ожидает дольше других.
Справедливый семафор обеспечивает порядок очереди, но имеет больше накладных расходов.


Deadlock (взаимная блокировка):
Если поток забывает вызвать release() после acquire(), это приведет к "утечке" разрешений.

Пул ресурсов:
Часто используется для ограничения числа потоков, работающих с одним и тем же ресурсом.

#Java #Training #Multithreading #Semaphore
CountDownLatch

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

Основные методы CountDownLatch

await(): Блокирует поток до тех пор, пока счетчик не станет равен 0.
countDown(): Уменьшает значение счетчика на 1.
getCount(): Возвращает текущее значение счетчика.
await(long timeout, TimeUnit unit): Ждет заданное время. Если счетчик не достигает 0 за указанное время, поток продолжит выполнение.


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

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
// Создаем CountDownLatch с начальным значением 3
CountDownLatch latch = new CountDownLatch(3);

// Потоки, выполняющие задачи
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " is working...");
try {
Thread.sleep(1000); // Имитация работы
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + " finished.");
latch.countDown(); // Уменьшаем значение счетчика
};

// Запускаем 3 потока
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}

System.out.println("Main thread is waiting for tasks to finish...");
latch.await(); // Ждем, пока счетчик не станет равен 0
System.out.println("All tasks are finished. Main thread resumes.");
}
}


Результат:
Основной поток будет ждать завершения всех 3 задач.
После выполнения всех потоков (latch.countDown() вызывается 3 раза), основной поток продолжит выполнение.


Нюансы CountDownLatch

Одноразовый:
CountDownLatch нельзя сбросить или переиспользовать. Если нужно использовать его несколько раз, рассмотрите использование CyclicBarrier.

Потокобезопасность:

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

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


Когда использовать Semaphore или CountDownLatch?

Используйте Semaphore, если нужно управлять доступом к ограниченным ресурсам (например, пул соединений).
Используйте CountDownLatch, если потоки должны дождаться выполнения определенного количества задач, прежде чем продолжить выполнение.


Реальные примеры

Semaphore: Ограничение количества одновременных соединений
Semaphore semaphore = new Semaphore(10); // Максимум 10 соединений

// Каждый поток пытается установить соединение
Runnable connectTask = () -> {
try {
semaphore.acquire();
System.out.println("Connection established by " + Thread.currentThread().getName());
Thread.sleep(2000); // Используем соединение
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println("Connection released by " + Thread.currentThread().getName());
semaphore.release();
}
};


CountDownLatch: Ожидание завершения загрузки данных
CountDownLatch latch = new CountDownLatch(3);

Runnable loadData = () -> {
try {
System.out.println(Thread.currentThread().getName() + " loading data...");
Thread.sleep(1000);
latch.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
};

new Thread(loadData).start();
new Thread(loadData).start();
new Thread(loadData).start();

latch.await();
System.out.println("All data loaded. Proceeding to next step.");


#Java #Training #Multithreading #CountDownLatch
Что выведет код?

public class Task221124_1 {
public static void main(String[] args) {
int[] arr = {3, 5, 7, 9, 11};
int result = modifyArray(arr);
System.out.println(result);
System.out.println(arr[1]);
}

public static int modifyArray(int[] array) {
int sum = 0;
for (int i = 0; i < array.length; i++) {
array[i] = array[i] % 2 == 0 ? array[i] / 2 : array[i] * 2;
sum += array[i];
}
return sum;
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
11%
35 5
44%
70 5
0%
35 10
44%
70 10
А потом Oracle и сделать из Pyton фраймворк Java😂😂😂

https://t.me/Java_for_beginner_dev

#Mems
Аннотация @Transactional

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

@Transactional — это аннотация, которая может быть применена к классу или методу, чтобы указать, что в рамках данного метода или всех методов класса должна использоваться транзакция.

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

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class PaymentService {

@Transactional
public void transferMoney(Long fromAccountId, Long toAccountId, double amount) {
// Операции с базой данных
debitAccount(fromAccountId, amount);
creditAccount(toAccountId, amount);
}

private void debitAccount(Long accountId, double amount) {
// Логика снятия средств
}

private void creditAccount(Long accountId, double amount) {
// Логика зачисления средств
}
}
В этом примере все операции внутри метода transferMoney выполняются в одной транзакции. Если любая операция завершится сбоем, все изменения будут откатаны.


Основные параметры @Transactional

@Transactional поддерживает ряд параметров, которые позволяют гибко управлять транзакциями:

propagation: Определяет, как должна быть организована транзакция при вызове метода.
REQUIRED (по умолчанию): Использует текущую транзакцию или создает новую.
REQUIRES_NEW: Всегда создает новую транзакцию.
NESTED: Создает вложенную транзакцию.
SUPPORTS: Метод может работать в контексте транзакции, но это не обязательно.


isolation: Уровень изоляции транзакции.
READ_UNCOMMITTED: Минимальная изоляция, данные могут быть "грязными".
READ_COMMITTED: Предотвращает "грязное" чтение.
REPEATABLE_READ: Предотвращает неповторяющееся чтение.
SERIALIZABLE: Максимальная изоляция, предотвращает все виды конфликтов.


timeout: Максимальное время выполнения транзакции в секундах.
readOnly: Указывает, что транзакция предназначена только для чтения данных.

rollbackFor и noRollbackFor: Исключения, при которых следует или не следует откатывать транзакцию.

Пример с параметрами:
@Transactional(
propagation = Propagation.REQUIRES_NEW,
isolation = Isolation.SERIALIZABLE,
timeout = 30,
rollbackFor = {RuntimeException.class},
readOnly = false
)
public void processTransaction() {
// Логика транзакции
}


Управление откатами

Spring автоматически откатывает транзакции, если метод генерирует RuntimeException или Error. Вы можете настроить это поведение с помощью rollbackFor.
@Transactional(rollbackFor = Exception.class)
public void updateDatabase() throws Exception {
// Если возникает Exception, транзакция будет откатана
}


Применение
@Transactional на уровне класса

Если аннотация используется на уровне класса, все методы будут выполняться в рамках транзакции.
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class OrderService {

public void createOrder() {
// Операции в транзакции
}

public void cancelOrder() {
// Операции в транзакции
}
}


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

Прокси: Spring использует прокси-объекты для управления транзакциями. Это означает, что вызовы методов внутри одного класса могут не учитывать аннотацию
@Transactional.

Пример проблемы:
@Service
public class ExampleService {

@Transactional
public void method1() {
method2(); // method2 вызван напрямую, @Transactional не применяется
}

@Transactional
public void method2() {
// Логика method2
}
}
Только публичные методы: Аннотация работает только на публичных методах. Внутренние вызовы приватных или protected методов не активируют транзакцию.


#Java #Training #Spring #Transactional
Всем доброго субботнего утра!✌️

Вот и пришли выходные, а с ними и завтрашний лайф-кодинг.

В этот раз мы напишем на Spring простой банковский сервис, главной фишкой которого является асинхронная обработка всех поступающих запросов на перевод денег между клиентами.
Также в рамках написания, мы рассмотрим основные вопросы многопоточноcти в Java.


А в остальном всем теплых и светлых выходных!🫡
This media is not supported in your browser
VIEW IN TELEGRAM
Всем привет!🖐

Сегодня в 16:00 по МСК жду Вас на лайф-кодинге! 😱

Напишем на Spring простое банковское CRUD-приложение с упором на многопоточку и протестируем его.

Ссылку на Яндекс.Телемост опубликую здесь за 15 минут до начала.✌️

До встречи!🤓
Оглавление обучающих постов часть 3. SPRING

Spring Framework
Архитектура Spring и его модули
Spring Framework's
Контейнер Inversion of Control (IoC)
Принципы Dependency Injection (DI)
Управление объектами в Spring Container
Конфигурация Spring через XML
Конфигурация Spring через аннотации
Основы Bean в Spring: создание и управление
Жизненный цикл бинов
Синглтон и Прототипы в Spring
Паттерны использования бинов в Spring
Spring. Внедрение зависимостей через конструктор
Spring. Внедрение зависимостей через сеттеры
@Autowired
@Qualifier
Контекст Spring: ApplicationContext и BeanFactory
Способы загрузки контекста в Spring
Жизненный цикл ApplicationContext в Spring
Построение приложения с использованием Java-конфигурации в Spring
@Component и @Service
@Repository в Spring
Способы работы с внешними конфигурациями в Spring: application.properties и application.yml
Валидация и валидационные аннотации в Spring
@Import
@Value

——SPRING MVC——

Spring MVC
Архитектура MVC в Spring
@Controller
@RequestMapping
@GetMapping, @PostMapping, @PutMapping и @DeleteMapping
@RequestBody
@ModelAttribute
@RequestParam и @PathVariable
ViewResolver
@ResponseBody
Как @RestController взаимодействует с @RequestMapping
JSP и Thymeleaf как механизмы представления
Конфигурация шаблонов Thymeleaf в Spring
Формы и отправка данных в Spring MVC
Обработка форм и привязка данных в Spring MVC
@ExceptionHandler
@ControllerAdvice

——SPRING JDBC——

Введение в Spring JDBC
Настройка DataSource и подключение к базе данных в Spring JDBC
Использование JdbcTemplate в Spring JDBC для выполнения SQL-запросов
Создание и выполнение CRUD операций через Spring JDBC
Введение в ORM и Spring Data JPA
@Entity, @Table, @Id
@Column, @GeneratedValue, @ManyToOne
@OneToOne, @ManyToMany, @JoinColumn, @Lob, @Query, @Modifying, @EnableJpaRepositories
@Embeddable, @Embedded, @ElementCollection, @Inheritance, @Cacheable, @Lock, @EntityListeners, @SQLInsert, @SQLUpdate, @SQLDelete
Сущности в JPA
Репозитории в Spring Data: интерфейс CrudRepository и JpaRepository
Создание методов для поиска данных в Spring Data JPA
Транзакции в Spring
@Transactional
Уровни изоляции транзакций и виды проблем
Управление транзакциями вручную
Rollback и Commit транзакций
Rollback с использованием @Transactional
Исключения в транзакциях
Оптимизация работы с транзакциями
Нюансы работы с транзакциями в Spring

#Contents
Оглавление для обучающих постов.

Если хотите найти информацию по Java, ранее опубликованную на канале - для Вас подготовлено оглавление уже из 3-х частей!

Пользуйтесь на здоровье!🫡

Часть 1.
Часть 2.
Часть 3. SPRING

Часть 2 дополнена.

Читайте, используйте, будут вопросы - пишите!😉
Простое Web приложение с асинхронной работой методов на Spring. Встреча от 24.11.2024

Запись нашей сегодняшней встречи -
YOUTUBE
RUTUBE

Спасибо всем кто пришел, за участие!💪

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

Кроме того в тесте к данному приложению рассмотрели различные варианты использования методов многопоточности.


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

Ссылка на GitHub - https://github.com/Oleborn/MultiThreadingSpringApp

Всем хорошего настроения! 🫡✌️
Уровни изоляции транзакций и виды проблем

Когда несколько транзакций работают одновременно, необходимо обеспечить согласованность данных. Для этого в реляционных базах данных применяются уровни изоляции. Они определяют, каким образом одна транзакция видит изменения, сделанные другой.

Уровни изоляции транзакций

SQL определяет четыре уровня изоляции. Каждый из них предлагает определенный баланс между производительностью и уровнем защиты от проблем параллелизма:

READ UNCOMMITTED (чтение незафиксированных данных)

Самый низкий уровень изоляции.
Транзакция может читать данные, которые еще не зафиксированы другой транзакцией.

Возможные проблемы: грязное чтение.

READ COMMITTED (чтение зафиксированных данных)

Гарантирует, что транзакция читает только данные, которые были зафиксированы.
Предотвращает грязное чтение, но не решает проблему неповторяемого чтения.


REPEATABLE READ (повторяемое чтение)

Обеспечивает, что данные, прочитанные в рамках транзакции, не изменятся, пока она не завершится.
Предотвращает грязное чтение и неповторяемое чтение, но не защищает от фантомных чтений.


SERIALIZABLE (серилизуемость)

Самый высокий уровень изоляции.
Транзакции выполняются последовательно, исключая все проблемы параллелизма.
Самый дорогой уровень с точки зрения производительности.


Виды проблем параллелизма

Грязное чтение (Dirty Read)
Одна транзакция читает данные, которые были изменены другой транзакцией, но не зафиксированы. Если вторая транзакция откатится, первая окажется с некорректными данными.
// Транзакция 1
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

// Транзакция 2 (до фиксации транзакции 1)
SELECT balance FROM accounts WHERE id = 1;


Неповторяемое чтение (Non-repeatable Read)
Данные, прочитанные одной транзакцией, могут быть изменены другой транзакцией до завершения первой.
// Транзакция 1
SELECT balance FROM accounts WHERE id = 1;

// Транзакция 2
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

// Транзакция 1 (повторное чтение)
SELECT balance FROM accounts WHERE id = 1;


Фантомное чтение (Phantom Read)
Транзакция читает набор строк, но другой транзакцией в этот набор добавляются новые строки.
// Транзакция 1
SELECT * FROM orders WHERE amount > 100;

// Транзакция 2
INSERT INTO orders (id, amount) VALUES (10, 150);

// Транзакция 1 (повторное чтение)
SELECT * FROM orders WHERE amount > 100;


Установка уровней изоляции в Spring

Уровень изоляции можно задать с помощью аннотации @Transactional:
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OrderService {

@Transactional(isolation = Isolation.READ_COMMITTED)
public void processOrder() {
// Логика обработки заказа
}
}


Spring поддерживает следующие уровни:
Isolation.READ_UNCOMMITTED
Isolation.READ_COMMITTED
Isolation.REPEATABLE_READ
Isolation.SERIALIZABLE


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

public class Task251124_1 {
public static void main(String[] args) {
String str = "aabbccddeeff";
String result = str.replace("aa", "x")
.replace("ee", "y")
.replace("xx", "z")
.replace("dd", "w");
System.out.println(result);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
27%
zbbccwfyff
7%
xbbccwfyff
0%
xbbccdyff
67%
xbbccwyff