Знания по базам данных на техсобесах игнорировать нельзя.
Честно, многие реально боятся DB. И когда бэкендер не может сходу написать обычный, часто используемый запрос, его шансы пройти начинают заметно проседать.
Один из ключевых концептов тут это JOIN.
Я собрал понятную шпаргалку по SQL JOIN: с примерами и визуализацией, чтобы быстро уложить в голове.
👉 Java Portal
Честно, многие реально боятся DB. И когда бэкендер не может сходу написать обычный, часто используемый запрос, его шансы пройти начинают заметно проседать.
Один из ключевых концептов тут это JOIN.
Я собрал понятную шпаргалку по SQL JOIN: с примерами и визуализацией, чтобы быстро уложить в голове.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍3💊1
Брейкпоинты в IDEA (IntelliJ и другие) для разработчиков
Иногда смотрю, как люди дебажат, и чуть ли не ловлю инсульт🍺
Большинство разработчиков умеют только ставить и удалять брейкпоинты. А в IDEA есть куча полезных фич для отладки. Ниже самые годные:
[1] Условие остановки
Если метод вызывается часто или брейкпоинт стоит в цикле, не трать время, ожидая нужных значений:
▪️ ПКМ по брейкпоинту
▪️ В Condition добавь условие остановки. Можно использовать все доступные переменные, объекты и методы
[2] Динамически смотреть значения параметров
Вариант для новичков: добавить в код
Вариант для продвинутых:
▪️ Зажми Shift и поставь брейкпоинт
▪️ Отметь чекбокс Evaluate and log
▪️ Введи нужное выражение
Дебаггер не будет останавливать выполнение, но будет писать значение выражения в консоль. Супер полезно для многопоточки, кода сторонних библиотек и remote debugging.
[3] Отключение брейкпоинта
Ненужный брейкпоинт можно не удалять, а просто выключить:
▪️ Нажми на шестеренку у брейкпоинта
ИЛИ
▪️ ПКМ по брейкпоинту → снимай галочку Enabled
[4] Массовая чистка
Когда в проекте много брейкпоинтов, IDE может чуть тормозить во время дебага. Чтобы убрать лишние, открой полный список:
▪️ ПКМ по любому брейкпоинту
▪️ Link More
▪️ Слева будет список брейкпоинтов
▪️ Удаляй ненужные
Обязательно попробуй. Пусть дебаг будет как по маслу👍
👉 Java Portal
Иногда смотрю, как люди дебажат, и чуть ли не ловлю инсульт
Большинство разработчиков умеют только ставить и удалять брейкпоинты. А в IDEA есть куча полезных фич для отладки. Ниже самые годные:
[1] Условие остановки
Если метод вызывается часто или брейкпоинт стоит в цикле, не трать время, ожидая нужных значений:
[2] Динамически смотреть значения параметров
Вариант для новичков: добавить в код
System.out.println с нужным полем/выражением.Вариант для продвинутых:
Дебаггер не будет останавливать выполнение, но будет писать значение выражения в консоль. Супер полезно для многопоточки, кода сторонних библиотек и remote debugging.
[3] Отключение брейкпоинта
Ненужный брейкпоинт можно не удалять, а просто выключить:
ИЛИ
[4] Массовая чистка
Когда в проекте много брейкпоинтов, IDE может чуть тормозить во время дебага. Чтобы убрать лишние, открой полный список:
Обязательно попробуй. Пусть дебаг будет как по маслу
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥8
Java 25: апгрейд, который экономит до 30% RAM (без правок кода)
В JDK 25 добавили одну из самых заметных оптимизаций за долгое время: Compact Object Headers (JEP 519).
Что меняется:
- размер заголовка объекта уменьшается примерно с ~12 байт до 8 байт
- меньше памяти на объект -> меньше heap
- меньше heap -> меньше давление на GC
- меньше GC -> сервис быстрее + облако дешевле
Где профит максимальный:
Spring Boot, микросервисы, DTO, records, кэши, в общем всё, где много мелких объектов.
Включается одной опцией:
-XX:+UseCompactObjectHeaders
По отзывам из реальных систем:
снижение heap на 15–30% встречается довольно часто.
Просто протестируй на своих сервисах и забирай “бесплатную” экономию.
👉 Java Portal
В JDK 25 добавили одну из самых заметных оптимизаций за долгое время: Compact Object Headers (JEP 519).
Что меняется:
- размер заголовка объекта уменьшается примерно с ~12 байт до 8 байт
- меньше памяти на объект -> меньше heap
- меньше heap -> меньше давление на GC
- меньше GC -> сервис быстрее + облако дешевле
Где профит максимальный:
Spring Boot, микросервисы, DTO, records, кэши, в общем всё, где много мелких объектов.
Включается одной опцией:
-XX:+UseCompactObjectHeaders
По отзывам из реальных систем:
снижение heap на 15–30% встречается довольно часто.
Просто протестируй на своих сервисах и забирай “бесплатную” экономию.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16
Java: Records не ограничены ролью просто контейнера данных, в них можно добавлять кастомные конструкторы и методы для валидации.
✅ В records можно иметь конструкторы, статические методы и методы экземпляра:
👉 Java Portal
public record Email(String address) {
// Конструктор с валидацией
public Email {
if (address == null || !address.matches("^[\\w-.]+@([\\w-]+\\.)+[\\w-]{2,4}$")) {
throw new IllegalArgumentException("Некорректный email-адрес: " + address);
}
}
// Метод экземпляра
public String domain() {
return address.substring(address.indexOf('@') + 1);
}
// Статический метод
public static Email from(String raw) {
return new Email(raw.trim().toLowerCase());
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
5👍7❤2
В Spring Boot можно включить асинхронное логирование, настроив Logback (logback-spring.xml).
✅ Лог-сообщения отправляются в очередь и обрабатываются отдельным фоновым потоком.
✅ Это снижает узкие места на I/O (ввод-вывод).
Положи конфиг Logback в папку
Пример:
👉 Java Portal
Положи конфиг Logback в папку
resources:src/main/resources/logback-spring.xmlПример:
<configuration>
<!-- Консольный appender, обернутый в async -->
<appender name="ASYNC_CONSOLE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="CONSOLE" />
<queueSize>5000</queueSize>
<discardingThreshold>0</discardingThreshold>
<includeCallerData>false</includeCallerData>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="ASYNC_CONSOLE" />
</root>
</configuration>
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3
Развенчиваем распространенный миф про Java Garbage Collector
Миф: мне НЕ нужно заниматься управлением памятью в Java, потому что GC все делает за меня
Garbage Collector (GC) действительно очищает неиспользуемые объекты, на которые больше нет активных ссылок. Благодаря этому в Java не нужно вручную освобождать память, как в C++.
Несколько предпосылок, из которых обычно рождается этот тезис:
- В языках с ручным управлением памятью (C, C++) утечки очевидны: если забыл вызвать
- В Java GC работает автоматически, поэтому кажется, что он сам решает все проблемы.
- «Ну раз есть GC, значит о памяти можно больше не думать» - типичная ошибка.
GC удаляет только те объекты, на которые больше нет активных ссылок. Если объект остается доступным, но фактически уже не используется, он будет занимать память до завершения приложения.
* Несколько случаев утечек памяти
[1] Статические коллекции (заполняем, но не очищаем)
Если создать
Через пару минут -
[2] Переменные потока (
Объекты, сохраненные в
Поток завершится, но память останется занятой, потому что
[3] Внутренние классы и «утекшие» ссылки
Если анонимный класс или lambda-ссылка захватывает внешний объект, это может мешать GC освободить его.
Миф развенчан. GC не всесилен, и даже с ним придется учиться правильно работать с памятью в Java.
👉 Java Portal
Миф: мне НЕ нужно заниматься управлением памятью в Java, потому что GC все делает за меня
Garbage Collector (GC) действительно очищает неиспользуемые объекты, на которые больше нет активных ссылок. Благодаря этому в Java не нужно вручную освобождать память, как в C++.
Несколько предпосылок, из которых обычно рождается этот тезис:
- В языках с ручным управлением памятью (C, C++) утечки очевидны: если забыл вызвать
free(), память потеряна навсегда.- В Java GC работает автоматически, поэтому кажется, что он сам решает все проблемы.
- «Ну раз есть GC, значит о памяти можно больше не думать» - типичная ошибка.
GC удаляет только те объекты, на которые больше нет активных ссылок. Если объект остается доступным, но фактически уже не используется, он будет занимать память до завершения приложения.
* Несколько случаев утечек памяти
[1] Статические коллекции (заполняем, но не очищаем)
Если создать
static List и постоянно добавлять в него объекты, GC их никогда не освободит, потому что статические поля живут в течение всего времени работы приложения.public class MemoryLeak {
private static final List<byte[]> cache = new ArrayList<>();
public static void main(String[] args) {
while (true) {
cache.add(new byte[10 * 1024 * 1024]);
System.out.println("Added 10MB to the cache. Used memory: " +
(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024) + "MB");
}
}
}Через пару минут -
OutOfMemoryError.[2] Переменные потока (
ThreadLocal)Объекты, сохраненные в
ThreadLocal, привязаны к потоку, а в пуле потоков могут жить дольше, чем нужно.public class ThreadLocalLeak {
private static final ThreadLocal<byte[]> threadLocalData = new ThreadLocal<>();
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
threadLocalData.set(new byte[10 * 1024 * 1024]); // 10MB per thread
System.out.println("Memory occupied by the thread!");
});
}
executor.shutdown();
}
}Поток завершится, но память останется занятой, потому что
ThreadLocal не очищается автоматически.[3] Внутренние классы и «утекшие» ссылки
Если анонимный класс или lambda-ссылка захватывает внешний объект, это может мешать GC освободить его.
public class InnerClassLeak {
private String data = "Very important data";
public void createAnonymousClass() {
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("Using: " + data);
}
};
new Thread(task).start();
}
}task держит ссылку на data, и даже если InnerClassLeak больше не используется, GC не сможет очистить объект.Миф развенчан. GC не всесилен, и даже с ним придется учиться правильно работать с памятью в Java.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2
Spring Boot: можно использовать
✅ Если что-то не совпадает, приложение не запустится
✅ Это можно комбинировать с инструментами миграций, например Flyway или Liquibase
👉 Java Portal
spring.jpa.hibernate.ddl-auto=validate, чтобы проверять случайные изменения схемы в продакшене.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2
Твоя база данных не медленная.
Медленный у тебя цикл обратной связи.
Один сеньор написал практический гайд, где показано, как разработчику на Java анализировать производительность PostgreSQL из Quarkus-приложения с помощью
👉 Java Portal
Медленный у тебя цикл обратной связи.
Один сеньор написал практический гайд, где показано, как разработчику на Java анализировать производительность PostgreSQL из Quarkus-приложения с помощью
pg_stat_statements, hypopg и PostgreSQL MCP-сервера через IBM Bob.Please open Telegram to view this post
VIEW IN TELEGRAM
The-Main-Thread
How to Find Database Performance Problems with Quarkus, PostgreSQL MCP, and AI
A practical guide for Java developers to analyze slow queries, missing indexes, and database health using Quarkus and IBM Bob
👍6❤1
Совет: держите код рядом. Следите, чтобы вычисление было как можно ближе к месту, где используется это значение. Это улучшает читаемость и удобство рефакторинга, снижает вероятность багов и делает код более устойчивым к ошибкам.
👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
Совет по Java: используйте
👉 Java Portal
Collectors.groupingBy(...), чтобы группировать результаты стрима по классификатору.Please open Telegram to view this post
VIEW IN TELEGRAM
👀4
Пессимистическая vs оптимистическая блокировка
Частый вопрос на собеседованиях по backend.
[Пессимистическая блокировка]: -
- Запись недоступна другим потокам, пока текущий поток не закончит с ней работу.
- Даже чтение данных другими потоками невозможно, пока блокировка не снята.
- Пример:
- Минусы: снижает производительность при высоком уровне конкуренции.
- Когда использовать: когда критически важна точность данных.
[Оптимистическая блокировка]: -
- Не блокирует данные при чтении, но при сохранении проверяет версию записи.
- Пример: аннотация
- Если версия изменилась другим потоком, выбрасывается
- Минусы: нужно разруливать конфликты.
- Когда использовать: когда чтений много, а вероятность конфликтов низкая.
Какой подход ты чаще используешь в своих проектах?
👉 Java Portal
Частый вопрос на собеседованиях по backend.
[Пессимистическая блокировка]: -
- Запись недоступна другим потокам, пока текущий поток не закончит с ней работу.
- Даже чтение данных другими потоками невозможно, пока блокировка не снята.
- Пример:
EntityManager.lock(entity, LockModeType.PESSIMISTIC_WRITE) в JPA.- Минусы: снижает производительность при высоком уровне конкуренции.
- Когда использовать: когда критически важна точность данных.
[Оптимистическая блокировка]: -
- Не блокирует данные при чтении, но при сохранении проверяет версию записи.
- Пример: аннотация
@Version в JPA (колонка для хранения версии).- Если версия изменилась другим потоком, выбрасывается
OptimisticLockException.- Минусы: нужно разруливать конфликты.
- Когда использовать: когда чтений много, а вероятность конфликтов низкая.
Какой подход ты чаще используешь в своих проектах?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
На Stepik добавили курс «Linux с нуля»
Этот курс закрывает всю обязательную Linux-базу для работы в IT. Подойдёт для:
Внутри 20+ модулей: от установки Linux и работы с файлами до сетей, прав, дисков, процессов, автоматизации на Bash и многого другого. Всё сразу закрепляется на практике (200+ заданий с автопроверкой)
Материал подаётся понятным языком, шаг за шагом, на реальных примерах и с наглядными схемами
После прохождения вы получите сертификат, который можно добавить в резюме.
В ближайшие 48ч курс доступен со скидкой 30% по промокоду «
Этот курс закрывает всю обязательную Linux-базу для работы в IT. Подойдёт для:
- разработчиков
- девопсов и админов
- специалистов по данным и ML
- специалистов поддержки и сопровождения
- тестировщиков и безопасников
Внутри 20+ модулей: от установки Linux и работы с файлами до сетей, прав, дисков, процессов, автоматизации на Bash и многого другого. Всё сразу закрепляется на практике (200+ заданий с автопроверкой)
Материал подаётся понятным языком, шаг за шагом, на реальных примерах и с наглядными схемами
После прохождения вы получите сертификат, который можно добавить в резюме.
В ближайшие 48ч курс доступен со скидкой 30% по промокоду «
PORTAL30»: открыть курс на Stepik❤2
Задумывался, как работают ActiveMQ и RabbitMQ?
В основе у них producer/consumer паттерн.
Как его реализовать?
Это базовая схема обмена данными между несколькими потоками. Поток-продюсер отправляет объекты на условную обработку, а потоки-консьюмеры асинхронно их получают и обрабатывают.
Общий вид решения такой:
продюсер кладет объекты в специальную коллекцию, буфер. Когда консьюмер освобождается, он запрашивает из буфера один объект. Если буфер пустой, консьюмер блокируется и ждёт; если буфер переполнен, ждёт продюсер.
Реализовать этот паттерн можно по-разному.
Самый правильный способ для продакшена: брать готовую реализацию из стандартной библиотеки, например
На собеседованиях обычно просят написать реализацию с нуля. На картинке показан один из вариантов.
Модификатор
👉 Java Portal
В основе у них producer/consumer паттерн.
Как его реализовать?
Это базовая схема обмена данными между несколькими потоками. Поток-продюсер отправляет объекты на условную обработку, а потоки-консьюмеры асинхронно их получают и обрабатывают.
Общий вид решения такой:
продюсер кладет объекты в специальную коллекцию, буфер. Когда консьюмер освобождается, он запрашивает из буфера один объект. Если буфер пустой, консьюмер блокируется и ждёт; если буфер переполнен, ждёт продюсер.
Реализовать этот паттерн можно по-разному.
Самый правильный способ для продакшена: брать готовую реализацию из стандартной библиотеки, например
BlockingQueue.На собеседованиях обычно просят написать реализацию с нуля. На картинке показан один из вариантов.
Модификатор
synchronized гарантирует, что в один момент времени выполняется только один из методов и только одним потоком. Этого достаточно для корректной работы, пока буфер не пуст и не переполнен. Когда буфер пустой или полный, управление явно передаётся продюсеру или консьюмеру соответственно через notify() и wait().Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Почему твой бэкенд начинает тупить на 10k юзеров, хотя на 100 всё летало
Обычно причина одна из этих:
1️⃣ N+1 запросы
→ один запрос незаметно триггерит сотню походов в БД
2️⃣ Нет индексов
→ на каждом поиске полный проход по таблице
3️⃣ Тяжелая работа синхронно
→ письма, обработка картинок прямо внутри request cycle
4️⃣ Нет стратегии кеширования
→ один и тот же запрос в БД выполняется 1000 раз
5️⃣ Единая точка отказа
→ один инстанс БД тащит на себе вообще всё
Приложение не стало внезапно медленным.
Оно просто доросло до момента, когда плохие решения стали заметны.
👉 Java Portal
Обычно причина одна из этих:
→ один запрос незаметно триггерит сотню походов в БД
→ на каждом поиске полный проход по таблице
→ письма, обработка картинок прямо внутри request cycle
→ один и тот же запрос в БД выполняется 1000 раз
→ один инстанс БД тащит на себе вообще всё
Приложение не стало внезапно медленным.
Оно просто доросло до момента, когда плохие решения стали заметны.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8❤2
Совет по Java:
Избавляет от
👉 Java Portal
Stream.toArray(Type[]::new) это аккуратный и типобезопасный способ получить массив из стрима.Избавляет от
Object[] и ручных кастов.Please open Telegram to view this post
VIEW IN TELEGRAM
👍3