Библиотека Java разработчика
10.2K subscribers
1.07K photos
595 videos
58 files
1.49K links
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate.


По всем вопросам @evgenycarter

РКН clck.ru/3KoGeP
Download Telegram
🚀 Подборка полезных IT каналов в Max


Системное администрирование, DevOps 📌

https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин
https://max.ru/channel_win_sysadmin Системный Администратор Windows
https://max.ru/channel_linux_admin Linux: Системный администратор
https://max.ru/channel_linuxmod Linux
https://max.ru/channel_i_linux Системный администратор
https://max.ru/channel_devopslib DevOps, SRE, Sysadmin
https://max.ru/channel_devops_star DevOps Star (Звезда Девопса)

Excel лайфхак 📌
https://t.me/Excel_lifehack Excel лайфхак

Английский с нуля 🇬🇧
https://max.ru/UchuEnglish

1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://max.ru/channel_DevLab1C 1С:Предприятие 8

Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
https://max.ru/channel_cpp_geek C++ geek

Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика

Программирование React📌
https://max.ru/react_lib React

Программирование Rust📌
https://max.ru/channel_rust_lib

Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика

Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
https://max.ru/channel_java_geek Java Geek

GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных

Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков

Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов

Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻

Шутки программистов 📌
https://max.ru/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free

Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров

Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике

Вакансии в IT📌
https://max.ru/progjob
https://max.ru/channel_rabotait

Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных

Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
👎3🤮3💩2😁1
🧠 JPA: не забывай про flush() перед clear() — иначе словишь баг

Если ты используешь EntityManager вручную, например, при батчевой вставке или обновлении, то, скорее всего, пишешь что-то вроде:


for (int i = 0; i < entities.size(); i++) {
em.persist(entities.get(i));
if (i % 50 == 0) {
em.clear(); // чтобы не росла память
}
}


⚠️ Но тут баг: без flush() перед clear() ты теряешь все неперсистенные изменения! Hibernate просто забудет про них.

Правильно так:


for (int i = 0; i < entities.size(); i++) {
em.persist(entities.get(i));
if (i % 50 == 0) {
em.flush();
em.clear();
}
}


📌 flush() гарантирует, что все накопленные изменения пойдут в базу, а clear() уже безопасно очищает контекст.

💡 Эта ошибка особенно коварна, потому что не всегда проявляется — зависит от настроек, триггеров в БД, кэша и т.д.

📲 Мы в MAX

👉@BookJava
👍4🔥1
Чем отличаются checked и unchecked исключения в java?

В Java исключения делятся на два основных типа: checked и unchecked. Разница между ними ключевая и касается как обработки, так и структуры кода.

Checked Exceptions (Проверяемые исключения)

Примеры: IOException, SQLException, FileNotFoundException

Отличия:
1. Проверяются компилятором — вы обязаны либо обработать их с помощью try-catch, либо явно пробросить (throws) в сигнатуре метода.
2. Производные от Exception, но не от RuntimeException.
3. Используются для ситуаций, которые можно разумно ожидать и обработать (например, отсутствие файла, проблемы с сетью).

Пример:

public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path); // может выбросить IOException
}




Unchecked Exceptions (Непроверяемые исключения)

Примеры: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException

Отличия:
1. Не проверяются компилятором — вы не обязаны их обрабатывать или декларировать.
2. Производные от RuntimeException.
3. Возникают в результате ошибок в логике программы или непредвиденных ситуаций.

Пример:

public void printLength(String str) {
System.out.println(str.length()); // может выбросить NullPointerException
}


Если кратко:

Checked — ошибки среды, требующие явной обработки.

Unchecked — ошибки в логике, ответственность программиста.

📲 Мы в MAX

👉@BookJava
👍4🔥21
🧠 Как избежать N+1 при использовании @OneToMany в JPA

Одна из самых коварных ловушек JPA - это N+1 проблема. Особенно часто она проявляется при @OneToMany, например:


@Entity
class Author {
@OneToMany(mappedBy = "author", fetch = FetchType.LAZY)
private List<Book> books;
}


Вы загружаете список авторов, а потом проходите по каждому и вызываете getBooks() — и BAM 💥: 1 запрос на авторов и N запросов на книги.

📌 Решение - @EntityGraph или JOIN FETCH
Оба варианта решают проблему, но @EntityGraph — декларативный и более гибкий способ:


@EntityGraph(attributePaths = "books")
List<Author> findAll(); // Spring Data JPA


⚡️ Или через JPQL:


@Query("SELECT a FROM Author a JOIN FETCH a.books")
List<Author> findAllWithBooks();


💡 Совет: всегда думайте о графе объектов. Если вам нужно сразу подтянуть связанные сущности — делайте это явно. Не надейтесь на LAZY по умолчанию.

⚠️ Осторожно с пагинацией и JOIN FETCH — могут появиться дубликаты или проблемы с LIMIT. В таких случаях лучше использовать @BatchSize или подзапросы.

📲 Мы в MAX

👉@BookJava
👍4👎1
🧠 JPA: подводный камень с @ElementCollection и fetch = FetchType.EAGER

Сегодня покажу, почему @ElementCollection(fetch = FetchType.EAGER) — скрытая угроза производительности и неожиданного поведения.

📌 Суть проблемы
При использовании @ElementCollection с EAGER Hibernate делает отдельный SELECT на каждую коллекцию, даже при JOIN FETCH на родительскую сущность.


@Entity
class User {
@Id Long id;

@ElementCollection(fetch = FetchType.EAGER)
List<String> tags;
}


Запрос findAll() приведёт к N+1 проблеме:
1 запрос на User, потом по одному на каждый tags.

💡 Почему это больно
Даже если вы используете JOIN FETCH на User, Hibernate не может сделать JOIN на @ElementCollection. Это ограничение — Hibernate всегда грузит коллекцию отдельным запросом.

⚠️ Особенно опасно при pagination
Если вы делаете Page<User> — Hibernate сначала грузит User'ов, а затем делает N запросов на коллекции. В проде это быстро становится проблемой.

Что делать
1. Делайте fetch = FetchType.LAZY (по умолчанию так и есть).
2. Если нужно подгрузить коллекцию — используйте @BatchSize:


@ElementCollection
@BatchSize(size = 20)
List<String> tags;


Или вручную:


SELECT u FROM User u LEFT JOIN FETCH u.tags WHERE u.id IN :ids


👉 Следи за @ElementCollection — он не так прост, как кажется.

📲 Мы в MAX

👉@BookJava
👍1
🧠 Сегодня покажу вам полезный трюк для Spring Boot: как элегантно валидировать параметры контроллера без лишнего кода.

Часто вижу, как в контроллерах вручную проверяют @RequestParam на пустоту или формат. Это шумит код и приводит к ошибкам.

Вместо этого используйте аннотации валидации прямо на параметрах:


@RestController
@RequestMapping("/api")
@Validated // Обязательно!
public class UserController {

@GetMapping("/users")
public List<User> getUsers(
@RequestParam @NotBlank String name,
@RequestParam @Min(18) int age
) {
// Если валидация не пройдена — автоматически вернётся 400 Bad Request
return userService.findUsers(name, age);
}
}


📌 Ключевые моменты:
- Обязательно ставим @Validated над классом контроллера.
- На параметры добавляем любые стандартные аннотации из jakarta.validation.constraints.
- Ошибки валидации Spring обработает автоматически через MethodArgumentNotValidException.

💡 Можно кастомизировать ответ на ошибку, добавив глобальный @ExceptionHandler.

⚠️ Без @Validated аннотации на контроллере валидация параметров работать не будет!

📲 Мы в MAX

👉@BookJava
👍31
🔴 Завтра тестовое собеседование с Java-разработчиком

5 августа(уже завтра!) в 19:00 по мск
приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.

Как это будет:
📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Сергею

Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.

Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot

Реклама.
О рекламодателе.
👍1
В Java instance initializer blocks (блоки инициализации экземпляра) выполняются в следующем порядке:

- Они выполняются каждый раз, когда создается новый объект класса.
- Выполнение происходит после вызова конструктора родительского класса (super()), но до тела конструктора текущего класса.

Порядок инициализации:

1. Сначала инициализируются поля в порядке их объявления.
2. Затем выполняются instance initializer blocks, в том порядке, в котором они написаны в коде.
3. После этого выполняется тело конструктора.

Пример:


class Example {
int x = 10;

{
System.out.println("Instance initializer block");
x = 20;
}

Example() {
System.out.println("Constructor");
System.out.println("x = " + x);
}

public static void main(String[] args) {
Example ex = new Example();
}
}


Вывод:

Instance initializer block
Constructor
x = 20


Ключевые моменты:
- Статические блоки (static {}) — другое дело: они выполняются один раз при загрузке класса.
- Instance initializer blocks полезны для общей инициализации, которую нужно выполнять вне зависимости от того, какой конструктор вызывается.

📲 Мы в MAX

👉@BookJava
👍3🔥2
🚀 Подборка полезных IT каналов в Max


Системное администрирование, DevOps 📌

https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин
https://max.ru/channel_win_sysadmin Системный Администратор Windows
https://max.ru/channel_linux_admin Linux: Системный администратор
https://max.ru/channel_linuxmod Linux
https://max.ru/channel_i_linux Системный администратор
https://max.ru/channel_devopslib DevOps, SRE, Sysadmin
https://max.ru/channel_devops_star DevOps Star (Звезда Девопса)

Excel лайфхак 📌
https://t.me/Excel_lifehack Excel лайфхак

Английский с нуля 🇬🇧
https://max.ru/UchuEnglish

1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://max.ru/channel_DevLab1C 1С:Предприятие 8

Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
https://max.ru/channel_cpp_geek C++ geek

Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика

Программирование React📌
https://max.ru/react_lib React

Программирование Rust📌
https://max.ru/channel_rust_lib

Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика

Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
https://max.ru/channel_java_geek Java Geek

GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных

Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков

Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов

Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻

Шутки программистов 📌
https://max.ru/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free

Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров

Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике

Вакансии в IT📌
https://max.ru/progjob
https://max.ru/channel_rabotait

Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных

Городские📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
https://max.ru/channel_krasnodar_novosty Краснодар Новости
https://max.ru/channel_novosibirsk_novosti Новосибирск
https://max.ru/channel_samara_novosti Новости Самары
https://max.ru/channel_ekaterinburg_novosti Новости Екатеринбурга
https://max.ru/channel_kazan_novosti Новости Казани
https://max.ru/channel_omsk_novosti Новости Омска
https://max.ru/channel_moskva_24 Москва 24
👎3
Как работают instance initializer blocks.


Пример с родительским и дочерним классами:


class Parent {
int a = 5;

{
System.out.println("Parent instance initializer");
a = 10;
}

Parent() {
System.out.println("Parent constructor, a = " + a);
}
}

class Child extends Parent {
int b = 15;

{
System.out.println("Child instance initializer");
b = 25;
}

Child() {
System.out.println("Child constructor, b = " + b);
}
}

public class Test {
public static void main(String[] args) {
Child child = new Child();
}
}



Вывод программы:


Parent instance initializer
Parent constructor, a = 10
Child instance initializer
Child constructor, b = 25


Пошаговое выполнение:

1. Сначала загружается родительский класс Parent.
2. Выполняется:
- Инициализация полей родителя (a = 5),
- Потом instance initializer блока родителя (a = 10),
- Потом конструктор родителя (Parent()).
3. Далее переходим к дочернему классу Child:
- Инициализация полей дочернего класса (b = 15),
- Потом instance initializer блока дочернего класса (b = 25),
- Потом конструктор дочернего класса (Child()).


Важный порядок действий:

1. Инициализация родителя → 2. Конструктор родителя → 3. Инициализация потомка → 4. Конструктор потомка.

Блоки инициализации всегда выполняются до тела конструктора, но после вызова super().

📲 Мы в MAX

👉@BookJava
👍6
💡Сегодня покажу крутую фишку для оптимизации чтения больших коллекций из базы через JPA.


📌 Проблема:
Когда загружаем большую коллекцию через @OneToMany, Hibernate часто делает это лениво (LAZY), но при первом доступе — забирает всю коллекцию целиком.
Это может привести к OutOfMemoryError или резкому проседанию производительности.


📌 Решение: использовать пагинацию (batch-size) или запрос коллекции порциями.

Как настроить batch-size на уровне сущности:


@Entity
public class User {

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
@BatchSize(size = 50)
private List<Order> orders;
}


🧠 Теперь Hibernate будет загружать за раз по 50 элементов, а не всю коллекцию сразу!


📌 Или можно настроить глобально через application.properties:


spring.jpa.properties.hibernate.default_batch_fetch_size=50



⚠️ Важно:

- @BatchSize работает только для LAZY-связей.
- Это не пагинация в SQL, а оптимизация внутренних запросов Hibernate.
- Если коллекция огромная (100k+ записей) — лучше делать явные paged запросы в репозитории.

💡Помните: без настройки batch-size Hibernate может сломать приложение под нагрузкой. Оптимизируйте загрузку коллекций заранее!

📲 Мы в MAX

👉@BookJava
👍3🔥1