Что выведет код?
Задача по Spring JDBC, использование JdbcTemplate, создание и выполнение CRUD операций в Spring. Сложность легкая.
Подробный разбор через 30 минут!🫡
#TasksSpring
Задача по Spring JDBC, использование JdbcTemplate, создание и выполнение CRUD операций в Spring. Сложность легкая.
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@SpringBootApplication
public class Main151124_2 {
public static void main(String[] args) {
SpringApplication.run(Main151124_2.class, args);
}
@Bean
public CommandLineRunner demo(JdbcTemplate jdbcTemplate) {
return args -> {
jdbcTemplate.execute("CREATE TABLE users (id INT AUTO_INCREMENT, name VARCHAR(255), age INT, PRIMARY KEY (id))");
jdbcTemplate.update("INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 30);
jdbcTemplate.update("INSERT INTO users (name, age) VALUES (?, ?)", "Bob", 25);
List<String> names = jdbcTemplate.query("SELECT name FROM users WHERE age > ?", new Object[]{20}, new NameRowMapper());
names.forEach(System.out::println);
};
}
static class NameRowMapper implements RowMapper<String> {
@Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString("name");
}
}
}
#TasksSpring
Подробный разбор решения задачи Task151124_2
1. Контекст задачи:
Эта задача демонстрирует использование Spring JDBC и JdbcTemplate для выполнения CRUD операций. В частности, в задаче показано, как с помощью JdbcTemplate можно создавать таблицы, вставлять данные, выполнять запросы и обрабатывать результаты с помощью RowMapper.
2. Ключевые элементы кода
Аннотация @SpringBootApplication:
@SpringBootApplication указывает, что Main151124_2 — это основной класс Spring Boot приложения. Она включает в себя @Configuration, @EnableAutoConfiguration и @ComponentScan, автоматически настраивая приложение и его компоненты, включая JdbcTemplate.
Аннотация @Bean и CommandLineRunner:
Метод demo() возвращает CommandLineRunner, который выполняется после запуска приложения. Это удобный способ выполнять код и тестировать логику работы с базой данных сразу после старта приложения.
JdbcTemplate:
JdbcTemplate предоставляет высокоуровневый API для работы с реляционными базами данных. Он упрощает выполнение SQL-запросов, управление соединениями и обработку результатов.
Методы execute и update используются для выполнения SQL-команд и вставки данных в таблицу.
Создание таблицы и вставка данных:
jdbcTemplate.execute("CREATE TABLE users ...") создает таблицу users с полями id, name и age.
jdbcTemplate.update("INSERT INTO users ...") вставляет две записи в таблицу: "Alice", 30 и "Bob", 25.
Запрос и использование RowMapper:
jdbcTemplate.query("SELECT name FROM users WHERE age > ?", new Object[]{20}, new NameRowMapper()) выполняет SELECT-запрос для получения имен пользователей с возрастом больше 20.
NameRowMapper реализует интерфейс RowMapper и используется для маппинга результатов запроса к объектам типа String. В данном случае, метод mapRow извлекает значение колонки name.
3. Сценарий работы программы
Запуск приложения:
Программа запускается с помощью SpringApplication.run(Main151124_2.class, args);, и Spring Boot настраивает встроенные компоненты, включая JdbcTemplate.
Выполнение операций с базой данных:
После запуска приложение создает таблицу users.
Затем добавляет две записи в таблицу:
Alice, возраст 30
Bob, возраст 25
Выполняется запрос SELECT name FROM users WHERE age > 20, который выбирает имена всех пользователей с возрастом больше 20.
Обработка результатов:
Запрос возвращает два имени: "Alice" и "Bob".
NameRowMapper преобразует строки результатов в объекты типа String.
Метод forEach выводит имена в консоль.
Вывод программы:
В консоль выводятся имена пользователей:
4. Ключевые моменты и выводы
Использование JdbcTemplate для работы с базой данных:
JdbcTemplate предоставляет удобные методы для выполнения SQL-запросов и управления результатами, устраняя необходимость ручного управления соединениями и обработкой исключений.
Создание и выполнение запросов:
execute используется для выполнения SQL-команд, таких как создание таблиц.
update подходит для выполнения операций вставки, обновления и удаления данных.
query используется для выполнения SELECT-запросов с маппингом результатов с помощью RowMapper.
RowMapper для преобразования результатов:
RowMapper преобразует строки результатов SQL-запросов в объекты Java. Это позволяет удобно обрабатывать данные и возвращать их в желаемом формате.
Валидация запросов и данных:
Запрос SELECT name FROM users WHERE age > 20 корректно выбирает всех пользователей, соответствующих условию, и возвращает их имена.
#Solution_TasksSpring
1. Контекст задачи:
Эта задача демонстрирует использование Spring JDBC и JdbcTemplate для выполнения CRUD операций. В частности, в задаче показано, как с помощью JdbcTemplate можно создавать таблицы, вставлять данные, выполнять запросы и обрабатывать результаты с помощью RowMapper.
2. Ключевые элементы кода
Аннотация @SpringBootApplication:
@SpringBootApplication указывает, что Main151124_2 — это основной класс Spring Boot приложения. Она включает в себя @Configuration, @EnableAutoConfiguration и @ComponentScan, автоматически настраивая приложение и его компоненты, включая JdbcTemplate.
Аннотация @Bean и CommandLineRunner:
Метод demo() возвращает CommandLineRunner, который выполняется после запуска приложения. Это удобный способ выполнять код и тестировать логику работы с базой данных сразу после старта приложения.
JdbcTemplate:
JdbcTemplate предоставляет высокоуровневый API для работы с реляционными базами данных. Он упрощает выполнение SQL-запросов, управление соединениями и обработку результатов.
Методы execute и update используются для выполнения SQL-команд и вставки данных в таблицу.
Создание таблицы и вставка данных:
jdbcTemplate.execute("CREATE TABLE users ...") создает таблицу users с полями id, name и age.
jdbcTemplate.update("INSERT INTO users ...") вставляет две записи в таблицу: "Alice", 30 и "Bob", 25.
Запрос и использование RowMapper:
jdbcTemplate.query("SELECT name FROM users WHERE age > ?", new Object[]{20}, new NameRowMapper()) выполняет SELECT-запрос для получения имен пользователей с возрастом больше 20.
NameRowMapper реализует интерфейс RowMapper и используется для маппинга результатов запроса к объектам типа String. В данном случае, метод mapRow извлекает значение колонки name.
3. Сценарий работы программы
Запуск приложения:
Программа запускается с помощью SpringApplication.run(Main151124_2.class, args);, и Spring Boot настраивает встроенные компоненты, включая JdbcTemplate.
Выполнение операций с базой данных:
После запуска приложение создает таблицу users.
Затем добавляет две записи в таблицу:
Alice, возраст 30
Bob, возраст 25
Выполняется запрос SELECT name FROM users WHERE age > 20, который выбирает имена всех пользователей с возрастом больше 20.
Обработка результатов:
Запрос возвращает два имени: "Alice" и "Bob".
NameRowMapper преобразует строки результатов в объекты типа String.
Метод forEach выводит имена в консоль.
Вывод программы:
В консоль выводятся имена пользователей:
Alice
Bob
4. Ключевые моменты и выводы
Использование JdbcTemplate для работы с базой данных:
JdbcTemplate предоставляет удобные методы для выполнения SQL-запросов и управления результатами, устраняя необходимость ручного управления соединениями и обработкой исключений.
Создание и выполнение запросов:
execute используется для выполнения SQL-команд, таких как создание таблиц.
update подходит для выполнения операций вставки, обновления и удаления данных.
query используется для выполнения SELECT-запросов с маппингом результатов с помощью RowMapper.
RowMapper для преобразования результатов:
RowMapper преобразует строки результатов SQL-запросов в объекты Java. Это позволяет удобно обрабатывать данные и возвращать их в желаемом формате.
Валидация запросов и данных:
Запрос SELECT name FROM users WHERE age > 20 корректно выбирает всех пользователей, соответствующих условию, и возвращает их имена.
#Solution_TasksSpring
Всем доброго утра! 🔆
И вот, нас посетили очередные выходные! 🫣
Какие у Вас планы на них? Позалипать за компьютером или выезд на зимнюю природу?😏
Кстати есть мысль устроить конкурс пет-проектов, интересно?)🧐
А вот насчет завтра идей пока нет. Думаю порешать задачки какие-нибудь))))
Накидайте идей что полайфкодить? ✌️
А в целом, всем прекрасных и плодотворных выходных😉
И вот, нас посетили очередные выходные! 🫣
Какие у Вас планы на них? Позалипать за компьютером или выезд на зимнюю природу?😏
Кстати есть мысль устроить конкурс пет-проектов, интересно?)🧐
А вот насчет завтра идей пока нет. Думаю порешать задачки какие-нибудь))))
Накидайте идей что полайфкодить? ✌️
А в целом, всем прекрасных и плодотворных выходных😉
Введение в 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 Data JPA
Создадим простое приложение для управления данными о пользователях.
1. Модель данных
2. Репозиторий
3. Сервисный слой
4. Контроллер
#Java #Training #Spring #SpringDataJPA
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
Что выведет код?
#Tasks
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
"А еще у них код грязный, потому что не моются месяцами" 🤪😂😂😂
https://t.me/Java_for_beginner_dev
#Mems
https://t.me/Java_for_beginner_dev
#Mems
Основные аннотации JPA: @Entity, @Table, @Id
1. Аннотация @Entity
@Entity указывает, что класс представляет собой сущность базы данных. Каждая сущность соответствует таблице в базе данных.
Пример:
2. Аннотация @Table
@Table используется для настройки имени таблицы и схемы, к которой относится сущность.
Пример:
3. Аннотация @Id
@Id используется для указания первичного ключа таблицы.
Пример:
Другие полезные аннотации
1. @GeneratedValue
Используется вместе с @Id для автоматической генерации значения первичного ключа.
Стратегии генерации:
AUTO — автоматически выбирает стратегию, зависящую от базы данных.
IDENTITY — использует автоинкремент в базе данных.
SEQUENCE — использует специальную таблицу для генерации уникальных значений.
TABLE — сохраняет последовательности значений в отдельной таблице.
2. @Column
Позволяет указать имя столбца, его уникальность, длину и другие параметры.
3. @Transient
Позволяет исключить поле из отображения в базе данных.
Пример полной конфигурации
#Java #Training #Spring #Entity #Table #Id #GeneratedValue #Column #Transient
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-выражение для явного указания типа столбца.
Пример использования:
В этом примере мы видим, что:
Поле username будет связано со столбцом username, не допускающим NULL и с максимальной длиной 50 символов.
Поле age связано со столбцом с SQL-типом INTEGER, по умолчанию равным 18.
2. Аннотация @GeneratedValue
Аннотация @GeneratedValue используется для указания стратегии генерации значений первичного ключа. Она применима к полям, помеченным как @Id.
Основные стратегии:
AUTO — выбор стратегии определяется провайдером JPA.
IDENTITY — генерация значения средствами базы данных.
SEQUENCE — использование последовательности, определенной в базе данных.
TABLE — использование таблицы для хранения значений идентификаторов.
Пример использования:
3. Аннотация @ManyToOne
Аннотация @ManyToOne используется для определения связи "многие к одному". Она обозначает, что текущее поле является ссылкой на другую сущность.
Пример использования:
#Java #Training #Spring #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:
Почему Race Condition?
count++ не является атомарной операцией.
Она состоит из трех шагов:
Чтение текущего значения count.
Увеличение значения.
Запись нового значения обратно в переменную.
Если оба потока прочитают одно и то же значение до записи, итоговое значение будет некорректным.
Deadlock (Взаимная блокировка)
Deadlock — ситуация, при которой два или более потоков блокируют друг друга, ожидая освобождения ресурсов.
Пример Deadlock:
Что происходит:
Поток 1 захватывает lock1 и ждет lock2.
Поток 2 захватывает lock2 и ждет lock1.
Оба потока застревают, ожидая освобождения ресурсов друг от друга.
#Java #Training #Multithreading #Medium #Race_Condition #Livelock #Starvation #Thread_Interference #Memory_Consistency_Errors #Multithreading_errors
Дополняю темы про распространенные ошибки многопоточности.
Распространенные ошибки многопоточности
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:
Что происходит:
Оба потока продолжают "уступать" друг другу, не завершив работу.
Starvation (Голодание)
Starvation — ситуация, когда поток постоянно лишается доступа к ресурсу из-за того, что другие потоки с более высоким приоритетом занимают его.
Причина: Использование приоритетов потоков, где высокоприоритетные потоки блокируют низкоприоритетные.
Thread Interference (Конфликт потоков)
Это ситуация, похожая на Race Condition, когда несколько потоков одновременно читают и изменяют общие данные, приводя к непредсказуемым результатам.
Пример:
Потоки выполняют операции на одной переменной без синхронизации, что приводит к некорректным итоговым значениям.
Memory Consistency Errors (Ошибки согласованности памяти)
Эти ошибки возникают, когда один поток изменяет данные, но другие потоки видят устаревшее состояние этих данных.
Причина: Использование кэша процессора.
Переменная, измененная в одном потоке, может не быть видимой для других потоков.
Решение:
Использование volatile для обеспечения видимости изменений.
Как предотвратить ошибки многопоточности
Использование синхронизации:
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
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
Что выведет код?
#Tasks
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
Варианты ответа:
Anonymous Quiz
17%
true false true false
33%
true true false false
50%
true true true false
0%
true true true true
Аннотации JPA: @OneToOne, @ManyToMany, @JoinColumn, @Lob, @Query, @Modifying, @EnableJpaRepositories
1. @OneToOne
Аннотация @OneToOne используется для определения связи "один к одному" между сущностями. Это может быть, например, связь между пользователем и его профилем.
2. @ManyToMany
@ManyToMany обозначает связь "многие ко многим". Это используется, когда несколько сущностей одной таблицы могут быть связаны с несколькими сущностями другой таблицы.
3. @JoinColumn
Аннотация @JoinColumn задаёт внешний ключ для связи. Она может использоваться с аннотациями @OneToOne и @ManyToOne.
4. @Lob
@Lob используется для маппинга больших объектов, таких как текстовые или бинарные данные.
5. @Query
Аннотация @Query позволяет задавать JPQL или SQL-запросы прямо в репозитории.
6. @Modifying
Используется вместе с @Query для выполнения операций обновления или удаления данных.
7. @EnableJpaRepositories
Эта аннотация активирует JPA-репозитории в Spring Boot.
#Java #Training #Spring #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 — указывает, что поле встраивает такой класс.
2. @ElementCollection
Используется для хранения коллекций простых типов или встраиваемых объектов.
3. @Inheritance
Настраивает стратегию наследования для сущностей.
4. @Cacheable
Обозначает, что сущность может быть закеширована.
5. @Lock
Используется для управления блокировками данных.
6. @EntityListeners
Позволяет подключать слушатели для отслеживания событий сущности.
7. @SQLInsert, @SQLUpdate, @SQLDelete
Эти аннотации позволяют задать кастомные SQL-запросы для операций вставки, обновления и удаления.
#Java #Training #Spring #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
Что выведет код?
#Tasks
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