Наш подписчик спрашивает:
Работаю джуном на проекте на Spring Boot и Hibernate. ORM вроде понятен — есть аннотации, Entity, Repository, всё работает «из коробки». Но недавно на собеседовании спросили, как работает JDBC под капотом, что такое PreparedStatement, и я понял, что знаю это очень поверхностно.
Возникает вопрос — стоит ли вообще углубляться в JDBC, если в проектах всё делается через ORM? Или это знания “для галочки”?
🔹 Что думаете?
Нужно ли джуну копать в сторону JDBC и понимать, как Hibernate общается с базой? Или достаточно знать ORM-уровень и двигаться дальше — в кэширование, оптимизацию запросов и т.п.?
— В каких кейсах применяете JDBC
— Насколько часто ORM «прячут» ошибки, которые проще понять через нативный SQL
— Что посоветуете джунам: когда стоит спуститься на уровень JDBC и зачем это вообще нужно
#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍3🔥1😁1
И вновь прошла насыщенная рабочая неделя. Сегодня немного сменилась локация, гуляю вдоль средиземного моря.
Как проходят ваши выходные?
Отправляйте фото в комментарии👇🏻
#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7😍2👍1
Когда в проекте сотни файлов и десятки классов — навигация превращается в хаос. А вы знали, что IDEA помнит все места, где вы недавно были?
🔹 Что делает
— Показывает список недавних мест в коде (не просто открытых файлов)
— Можно искать по содержимому, не только по имени
— Можно найти только изменённые фрагменты
🔹 Зачем это нужно
— Молниеносно возвращает к недавнему месту редактирования
— Полезно при ревью, багфиксе или исследовании сложных фрагментов
— Работает лучше, чем "Recent Files", ведь учитывает даже переходы внутри одного файла
🔹 Как использовать
— Нажмите
Ctrl+Shift+E
(Windows/Linux) или ⌘+Shift+E
(macOS)— Появится список последних мест где вы были. Можно также искать лишь изменённые фрагменты (повторно нажмите то же сочетание)
— Начните вводить фрагмент кода или имени и IDEA сама сузит поиск
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍6❤2
Forwarded from Библиотека собеса по Java | вопросы с собеседований
ConcurrentHashMap использует
В отличие от Collections.synchronizedMap(...), который
#concurrency
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4👏1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁20😢3💯2⚡1
🎯 Как быстро настроить Zero-Downtime деплой Spring Boot-приложения с помощью Docker + Traefik
Обновлять сервис без остановки — не роскошь, а необходимость. Ни пользователи, ни ваши коллеги не должны видеть "502 Bad Gateway", пока вы выкатываете новую версию.
Пошагово разберём, как сделать быстрый и бесшовный деплой с балансировкой между версиями.
1️⃣ Готовим Dockerfile
Собираем образ:
2️⃣ Добавляем Traefik как reverse proxy
Создаём docker-compose.yml:
version: '3.8'
Запускаем:
Traefik автоматически поднимет роутер и начнёт проксировать трафик.
3️⃣ Выкатываем новую версию без даунтайма
Создаём новый образ:
Добавляем в docker-compose.yml рядом:
Теперь Traefik балансирует между двумя версиями — 1.0.0 и 1.1.0.
Можно спокойно проверить, что новая версия работает корректно.
4️⃣ Плавно отключаем старую
Если всё ок — выключаем старый контейнер:
Traefik мгновенно перестроит маршрут — без обрывов соединений.
Ни один пользователь не заметит переключения.
5️⃣ Добавляем health-checks для надёжности
В application.yml:
И в Docker-compose:
Traefik будет держать в балансе только живые инстансы.
Всё просто и надёжно.
💡 Что мы получили:
— Обновления без простоев
— Автоматическую балансировку
— Self-healing через health-checks
— Легко масштабируемую инфраструктуру для staging/prod
🐸 Библиотека джависта
#Enterprise
Обновлять сервис без остановки — не роскошь, а необходимость. Ни пользователи, ни ваши коллеги не должны видеть "502 Bad Gateway", пока вы выкатываете новую версию.
Пошагово разберём, как сделать быстрый и бесшовный деплой с балансировкой между версиями.
FROM eclipse-temurin:21-jdk
WORKDIR /app
COPY target/myapp.jar app.jar
ENTRYPOINT ["java","-jar","/app/app.jar"]
Собираем образ:
docker build -t myapp:1.0.0 .
Создаём docker-compose.yml:
version: '3.8'
services:
traefik:
image: traefik:v3.1
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
myapp_v1:
image: myapp:1.0.0
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`myapp.local`)"
- "traefik.http.services.myapp.loadbalancer.server.port=8080"
Запускаем:
docker compose up -d
Traefik автоматически поднимет роутер и начнёт проксировать трафик.
Создаём новый образ:
docker build -t myapp:1.1.0 .
Добавляем в docker-compose.yml рядом:
myapp_v2:
image: myapp:1.1.0
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`myapp.local`)"
- "traefik.http.services.myapp.loadbalancer.server.port=8080"
Теперь Traefik балансирует между двумя версиями — 1.0.0 и 1.1.0.
Можно спокойно проверить, что новая версия работает корректно.
Если всё ок — выключаем старый контейнер:
docker compose stop myapp_v1
docker compose rm -f myapp_v1
Traefik мгновенно перестроит маршрут — без обрывов соединений.
Ни один пользователь не заметит переключения.
В application.yml:
management:
endpoints:
web:
exposure:
include: health
И в Docker-compose:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 10s
timeout: 3s
retries: 3
Traefik будет держать в балансе только живые инстансы.
Всё просто и надёжно.
— Обновления без простоев
— Автоматическую балансировку
— Self-healing через health-checks
— Легко масштабируемую инфраструктуру для staging/prod
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1👏1🤔1
👀 Внутреннее устройство CopyOnWriteArrayList
CopyOnWriteArrayList — это потокобезопасная коллекция из пакета java.util.concurrent, которая реализует интерфейсы List и RandomAccess. Она часто воспринимается как «волшебная таблетка» для многопоточности, но под капотом это хитрая стратегия: каждое изменение списка создаёт копию массива.
📦 Базовая структура
Внутри CopyOnWriteArrayList хранит данные в обычном массиве
— Все операции чтения (get, iterator, contains) идут напрямую по этому массиву и не требуют синхронизации.
— При модификациях (add, remove, set) создаётся новый массив с учётом изменений, и ссылка array указывает на него.
За счёт этого чтения не блокируются, а итераторы всегда видят снимок состояния (snapshot) на момент создания.
⚡️ Добавление и удаление
— add(E e): берётся текущий массив, копируется в новый на +1 элемент, в конец добавляется e.
— remove(Object o): копия массива создаётся без указанного элемента.
— set(int index, E element): создаётся копия массива, в которой меняется один элемент.
Сложность таких операций — O(n), ведь нужно копировать массив.
🌊 Итераторы
— Итератор у CopyOnWriteArrayList не fail-fast, в отличие от ArrayList и LinkedList.
— Он работает по «снимку» массива, который существовал в момент вызова iterator().
— Изменения, сделанные другими потоками, в процессе обхода не видны.
📊 Производительность
— Чтение (get, contains, iteration) → O(1) / O(n) для поиска очень быстро, так как обращение к массиву.
— Запись (add, remove, set) → O(n), так как требуется копировать массив.
— Итерация → O(n), но без блокировок и с высокой стабильностью в многопоточной среде.
⚖️ Важные нюансы
— CopyOnWriteArrayList идеален для сценариев «много чтений, мало записей».
— Память расходуется щедро: каждый апдейт порождает новую копию массива.
— Если записи происходят часто, использование становится неоправданным.
🧮 Когда использовать
— Подписчики/слушатели событий (например, listeners в UI или логгере).
— Кэш статических данных, где обновления редки.
— Конфигурации, которые меняются редко, а читаются часто.
В большинстве остальных случаев лучше использовать другие структуры (ConcurrentHashMap, Collections.synchronizedList, CopyOnWriteArraySet).
🔗 Документация: официальная JavaDoc (Java 17)
Ставьте 🔥, если хотите такой же пост по другим коллекциям. Пишите в комменты, какую коллекцию разобрать следующей.
🐸 Библиотека джависта
#CoreJava
CopyOnWriteArrayList — это потокобезопасная коллекция из пакета java.util.concurrent, которая реализует интерфейсы List и RandomAccess. Она часто воспринимается как «волшебная таблетка» для многопоточности, но под капотом это хитрая стратегия: каждое изменение списка создаёт копию массива.
📦 Базовая структура
Внутри CopyOnWriteArrayList хранит данные в обычном массиве
transient volatile Object[] array
.— Все операции чтения (get, iterator, contains) идут напрямую по этому массиву и не требуют синхронизации.
— При модификациях (add, remove, set) создаётся новый массив с учётом изменений, и ссылка array указывает на него.
За счёт этого чтения не блокируются, а итераторы всегда видят снимок состояния (snapshot) на момент создания.
⚡️ Добавление и удаление
— add(E e): берётся текущий массив, копируется в новый на +1 элемент, в конец добавляется e.
— remove(Object o): копия массива создаётся без указанного элемента.
— set(int index, E element): создаётся копия массива, в которой меняется один элемент.
Сложность таких операций — O(n), ведь нужно копировать массив.
🌊 Итераторы
— Итератор у CopyOnWriteArrayList не fail-fast, в отличие от ArrayList и LinkedList.
— Он работает по «снимку» массива, который существовал в момент вызова iterator().
— Изменения, сделанные другими потоками, в процессе обхода не видны.
📊 Производительность
— Чтение (get, contains, iteration) → O(1) / O(n) для поиска очень быстро, так как обращение к массиву.
— Запись (add, remove, set) → O(n), так как требуется копировать массив.
— Итерация → O(n), но без блокировок и с высокой стабильностью в многопоточной среде.
⚖️ Важные нюансы
— CopyOnWriteArrayList идеален для сценариев «много чтений, мало записей».
— Память расходуется щедро: каждый апдейт порождает новую копию массива.
— Если записи происходят часто, использование становится неоправданным.
🧮 Когда использовать
— Подписчики/слушатели событий (например, listeners в UI или логгере).
— Кэш статических данных, где обновления редки.
— Конфигурации, которые меняются редко, а читаются часто.
В большинстве остальных случаев лучше использовать другие структуры (ConcurrentHashMap, Collections.synchronizedList, CopyOnWriteArraySet).
Ставьте 🔥, если хотите такой же пост по другим коллекциям. Пишите в комменты, какую коллекцию разобрать следующей.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍3👏1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁30👍4🌚2👏1🤩1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁17❤12👍3💯2
🔥 Коллеги, годный практикум по микросервисной архитектуре!
По шагам — чем «учебный» монолит отличается от продакшна:
— observability-стек 👀 (Grafana/Prometheus/Loki/Tempo/Alloy),
— распределённые транзакции по Saga 🔄 (оркестрация/хореография),
— безопасность на Keycloak 🔐,
— API Gateway, OpenAPI + codegen 🚪 (DTO/Feign),
— инфраструктура на Docker Compose + Makefile + Nexus 🐳.
В конце — полный прогон: Docker → Postman → метрики/трейсы в Grafana.
▶️ Смотреть: Основы работы с микросервисами
P.S. У автора — техканал с продолжением темы: https://t.me/esuleimanov 🤓
По шагам — чем «учебный» монолит отличается от продакшна:
— observability-стек 👀 (Grafana/Prometheus/Loki/Tempo/Alloy),
— распределённые транзакции по Saga 🔄 (оркестрация/хореография),
— безопасность на Keycloak 🔐,
— API Gateway, OpenAPI + codegen 🚪 (DTO/Feign),
— инфраструктура на Docker Compose + Makefile + Nexus 🐳.
В конце — полный прогон: Docker → Postman → метрики/трейсы в Grafana.
▶️ Смотреть: Основы работы с микросервисами
P.S. У автора — техканал с продолжением темы: https://t.me/esuleimanov 🤓
👍6🤔2❤1😁1
Forwarded from Библиотека задач по Java | тесты, код, задания
Что будет результатом кода?
Anonymous Quiz
28%
Значение меньше 2000
43%
Всегда 2000
6%
Ошибка компиляции
12%
ConcurrentModificationException
11%
Посмотреть ответ
👍3❤1🔥1
⚡️ Просто о сложном: JIT-компилятор
Чтобы ускорить работу приложения, JVM включает в дело Just-In-Time (JIT) компилятор.
Он превращает часто выполняемый байткод в нативные машинные инструкции прямо во время исполнения.
🔹 Как это работает
— При старте приложения JVM интерпретирует байткод.
— Когда видит, например, что метод вызывается часто (т.н. hot method), — JIT компилирует его в машинный код.
— В следующий раз этот метод исполняется уже как нативный, без интерпретации.
— Всё это происходит «на лету» — поэтому Java-программы разгоняются после первых секунд работы.
🔹 Зачем нужен JIT
Он сочетает плюсы интерпретации и компиляции:
— Быстрый старт приложения (интерпретация).
— Высокая производительность после разогрева (JIT).
🔹 Что он умеет оптимизировать
— Inlining: подставляет код мелких методов прямо в место вызова.
— Escape Analysis: определяет, можно ли объект хранить на стеке вместо heap.
— Loop unrolling: разворачивает циклы для ускорения.
— Dead code elimination: выбрасывает ненужные операции.
— И другие алгоритмы.
⚙️ Как посмотреть, что делает JIT
Включите флаг:
И увидите, какие методы компилируются во время исполнения.
Интересно почитать про алгоритмы JIT подробнее → ставь 👾
🐸 Библиотека джависта
#CoreJava
Чтобы ускорить работу приложения, JVM включает в дело Just-In-Time (JIT) компилятор.
Он превращает часто выполняемый байткод в нативные машинные инструкции прямо во время исполнения.
🔹 Как это работает
— При старте приложения JVM интерпретирует байткод.
— Когда видит, например, что метод вызывается часто (т.н. hot method), — JIT компилирует его в машинный код.
— В следующий раз этот метод исполняется уже как нативный, без интерпретации.
— Всё это происходит «на лету» — поэтому Java-программы разгоняются после первых секунд работы.
🔹 Зачем нужен JIT
Он сочетает плюсы интерпретации и компиляции:
— Быстрый старт приложения (интерпретация).
— Высокая производительность после разогрева (JIT).
🔹 Что он умеет оптимизировать
— Inlining: подставляет код мелких методов прямо в место вызова.
— Escape Analysis: определяет, можно ли объект хранить на стеке вместо heap.
— Loop unrolling: разворачивает циклы для ускорения.
— Dead code elimination: выбрасывает ненужные операции.
— И другие алгоритмы.
Включите флаг:
-XX:+PrintCompilation
И увидите, какие методы компилируются во время исполнения.
Интересно почитать про алгоритмы JIT подробнее → ставь 👾
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👾11🔥2👍1