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


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

РКН clck.ru/3KoGeP
Download Telegram
👩‍💻 Открытый урок «Облака и Mongo DB Atlas»

🗓 12 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Разработчик на Spring Framework»

Погружаемся в мир облачных технологий и учимся разворачивать кластер MongoDB бесплатно.

Программа вебинара:
✔️ Облачные технологии: что такое облака, какие бывают уровни (IaaS, PaaS, SaaS) с простыми аналогиями для понимания.
✔️ Практическая демонстрация: как создать кластер MongoDB в Atlas и подключиться к нему.

Вебинар будет полезен:
Разработчикам, начинающим backend-программистам, студентам IT-курсов и всем, кто хочет разобраться в облачных сервисах.

В результате вебинара вы:
Научитесь создавать кластеры MongoDB в облаке.

🔗 Ссылка на регистрацию: https://vk.cc/cLJqe0

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🧠 Неочевидный performance-трюк с @Transactional(readOnly = true)

Многие используют @Transactional(readOnly = true) просто по инерции. Но вы знали, что в Spring это влияет не только на семантику, но и на производительность?

📌 Что делает readOnly = true:

* Подсказывает Hibernate, что внутри транзакции не будет изменений сущностей.
* Это позволяет избежать затрат на грязную проверку (dirty checking).
* Не создаётся snapshot состояний сущностей → меньше памяти и операций.

💡 Пример:


@Transactional(readOnly = true)
public List<User> findActiveUsers() {
return userRepository.findByActiveTrue();
}


⚠️ А теперь важно: если вы случайно измените сущность в таком методе, Hibernate проигнорирует изменения — потому что readOnly намекает: "не трогай".

📉 В реальном приложении с большим количеством запросов к БД, особенно читающих, такой подход даёт ощутимый буст — меньше нагрузки на ORM, меньше GC, быстрее ответы.

📌 Где применять:

* Методы только для чтения.
* REST-эндпоинты GET.
* Сервис-методы, возвращающие DTO и не модифицирующие Entity.

⚠️ Где не надо:

* Методы с lazy-loading и последующими модификациями.
* Там, где возможно случайное изменение Entity (например, через mapper'ы).

👉 Используйте @Transactional(readOnly = true) не как декор, а как инструмент для оптимизации.

👉@BookJava
👍9
🚀 Подборка Telegram каналов для программистов

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

https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux

1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С

Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах

Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python

Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах

GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub

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

Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin

Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано

Разработка игр 📌
https://t.me/game_devv Все о разработке игр

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

БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning

Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.

QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика

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

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

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

Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика

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

https://t.me/mir_teh Мир технологий (Technology World)

Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
🧠 Трюк с @Configuration и @ComponentScan: как не словить баг при миграции на Spring Boot 3+

Когда вы выносите конфигурацию в отдельный модуль или создаёте библиотеку с @Configuration-классами — не забывайте:

📌 Spring Boot 3+ по умолчанию НЕ сканирует пакеты вне стартового (main).

Пример:


// Внутри библиотеки
@Configuration
public class MyLibConfig {
@Bean
public MyService myService() {
return new MyService();
}
}


И вы такие:


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


🔥 Но MyService не создаётся! Почему?

💡 Потому что @ComponentScan по умолчанию сканирует ТОЛЬКО package текущего класса и ниже.

📌 Решения:

1. Ручной импорт конфигурации:


@SpringBootApplication
@Import(MyLibConfig.class)
public class App { ... }


2. Сделать конфигурацию @AutoConfiguration и подключить через spring.factories или META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports — актуально для библиотек.

3. Переместить MyLibConfig в подпакет стартового класса (не всегда возможно или удобно).

⚠️ Часто баг проявляется неявно: контекст стартует, но бины "теряются", и вы получаете NoSuchBeanDefinitionException в рантайме.

После миграции на Spring Boot 3+ обязательно проверьте, что нужные конфигурации действительно подхватываются. Особенно, если раньше они подключались "магически".

👉@BookJava
👍6
🔧 Maven vs. Gradle: что выбрать разработчику?

Когда речь заходит о сборке Java-проектов, выбор обычно падает на два главных инструмента: Maven и Gradle. Оба давно стали стандартом индустрии, но каждый имеет свои особенности. Разберёмся, что выбрать 👇

Maven — проверенная классика

Строгая структура: легче читать и сопровождать
Надёжность и предсказуемость сборки
Большое комьюнити и множество плагинов
⚠️ XML-конфигурация громоздкая
⚠️ Медленнее по сравнению с Gradle

Gradle — гибкость и скорость

Поддержка Kotlin и Groovy DSL
Инкрементальные сборки и кэширование → быстрее
Более гибкий подход к настройке
⚠️ Порог входа выше
⚠️ Иногда сложно отлаживать конфигурацию


💡 Вывод:

* 🔹 Выбирай Maven, если важны стабильность, простота и читаемость.
* 🔹 Выбирай Gradle, если хочешь максимум производительности и гибкости.

🎯 В крупных проектах Gradle становится всё популярнее, особенно при использовании Kotlin. Но в enterprise-среде Maven по-прежнему правит бал.

А ты чем пользуешься? Делись опытом в комментах ⬇️

👉@BookJava
👍9
🔍Тестовое собеседование на Middle Java-разработчика завтра

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

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

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

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

Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2VtzqxZCqXi
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
💡 Чем опасен @Scheduled(fixedRate) без @Transactional?

Расписание в Spring через @Scheduled — удобный способ запускать задачи по таймеру. Но часто разработчики забывают про транзакции, особенно с fixedRate, и попадают в ловушку.

📌 Пример проблемы:


@Scheduled(fixedRate = 10_000)
public void cleanUp() {
List<Job> jobs = jobRepository.findAllByStatus(PENDING);
jobs.forEach(job -> {
job.setStatus(PROCESSING);
jobRepository.save(job);
});
}


🧨 Каждые 10 секунд метод запускается заново. Если выполнение предыдущего ещё не закончено, начнётся второй поток, который заберёт те же PENDING -записи.
В итоге — дублирование обработки, гонки, повреждение данных.

📉 Особенно критично при долгих задачах или высокой нагрузке.

Решение — обернуть метод в транзакцию + использовать блокировки:


@Transactional
@Scheduled(fixedRate = 10_000)
public void cleanUp() {
List<Job> jobs = jobRepository.findAllByStatusForUpdate(PENDING); // SELECT ... FOR UPDATE
jobs.forEach(job -> {
job.setStatus(PROCESSING);
jobRepository.save(job);
});
}


📌 Или добавить флаг “locked”, чтобы явно помечать взятые задачи.

💡 Лучше использовать @Scheduled(fixedDelay) — он ждёт завершения предыдущего запуска. Это безопаснее по умолчанию.

🧠 Подумайте о том, чтобы заменить @Scheduled на:

* Spring Batch (если сложные джобы)
* Spring Integration / Flowable / Camunda (если нужны гарантии и retry)
* Quartz (если нужен контроль и очереди)

👉@BookJava
🔥7👍2
Возможности Kotlin для создания DSL на примере JsonBuilder

Приглашаем на открытый урок.

🗓 22 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Kotlin Backend Developer. Professional».

Что вас ждёт:
✔️ рассмотрим общую теорию о DSL: назначение, особенности, практика;
✔️ попрактикуемся в создании DSL на примере JsonBuilder;
✔️ рассмотрим возможности Kotlin, полезные для создания DSL.

🎁 Всем участникам вебинара дарим промокод, который дает скидку на обучение - Kotlin5

👉 Регистрация на вебинар: https://vk.cc/cLUdvA

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🧠 Spring Boot: ленивые зависимости через ObjectProvider

Иногда сервису не нужно всегда инжектить другую зависимость при старте — только иногда по ходу работы. Но @Autowired всё равно тянет её сразу, даже если она вам пока не нужна. Это бьёт по времени старта и может вызвать циклические зависимости.

💡 Решение: использовать ObjectProvider<T>.

Пример:


@Service
public class NotificationService {

private final ObjectProvider<EmailSender> emailSenderProvider;

public NotificationService(ObjectProvider<EmailSender> emailSenderProvider) {
this.emailSenderProvider = emailSenderProvider;
}

public void sendEmailIfEnabled(String to, String body) {
if (featureEnabled()) {
EmailSender sender = emailSenderProvider.getIfAvailable();
if (sender != null) {
sender.send(to, body);
}
}
}
}


📌 ObjectProvider:

▫️не создаёт бин сразу — ленивый доступ;
▫️ позволяет проверить наличие бина (getIfAvailable() / ifAvailable(...));
▫️можно использовать stream() — для коллекций бинов.

⚠️ Это не альтернатива DI. Это способ контролировать создание и использование бинов вручную, когда это действительно нужно.

📈 Отлично помогает:

▫️при борьбе с циклическими зависимостями;
▫️для optional-бинов;
▫️чтобы ускорить старт приложения.

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Хотите овладеть Spark на профессиональном уровне?

Приглашаем дата-инженеров 26 мая в 20:00 на открытый урок «Spark в Kubernetes».

На занятии мы рассмотрим особенности и варианты запуска Spark в Kubernetes.

🔊 Вебинар проведет Вадим Заигрин, Team Lead команд инженеров данных на разных проектах.

Продолжить освоение инструментов дата-инжиниринга вы сможете на онлайн-курсе «Spark Developer» от OTUS.

➡️ Ссылка для регистрации: https://vk.cc/cLWZuO

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👎2
🧠 Внезапная ловушка с @Transactional и self-invocation в Spring

Вы знали, что вызов метода с @Transactional внутри того же класса не активирует транзакцию? Это один из самых частых подводных камней.

📌 Почему так происходит?
Spring AOP работает через прокси. Когда вы вызываете метод this.someTransactionalMethod(), вы обходите прокси и вызываете метод напрямую — без обёртки, которая включает транзакцию.

Пример:


@Service
public class UserService {

public void createUser() {
// транзакция не начнётся
this.saveUser();
}

@Transactional
public void saveUser() {
// ожидаем, что тут будет транзакция, но её нет
}
}


⚠️ Итог: никакой транзакции, и вы получите баг, который сложно заметить: данные не откатываются, lazy-loading кидает LazyInitializationException, и т.д.

💡 Как правильно:

1. Вынести transactional-метод в другой бин:


@Service
public class UserSaver {
@Transactional
public void saveUser() { ... }
}


2. Или получить прокси текущего бина через AopContext:


public void createUser() {
((UserService) AopContext.currentProxy()).saveUser();
}


📌 Для второго варианта не забудьте включить:


@EnableAspectJAutoProxy(exposeProxy = true)


⚠️ Важно: Не используйте AopContext без крайней необходимости. Предпочтительнее делегировать логику в отдельный бин — это чище и легче тестируется.

👉@BookJava
👍4👎2
👩‍💻 SpELые приложения на Spring

Присоединяйтесь к открытому уроку, узнайте, как динамически выражать и обрабатывать данные в Spring-приложениях.

🗓 21 мая в 19:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Разработчик на Spring Framework».

О чём поговорим:
✔️Разоберем, для чего нужен SpEL.
✔️Рассмотрим, в каких проектах Spring его можно встретить.

Кому будет интересно:
Spring-разработчикам, Java-бэкенд-инженерам, архитекторам ПО, IT-специалистам и студентам, заинтересованным в технологиях Spring.

В результате урока:
Узнаете, для чего нужен SpEL и где его можно применять.

🔗 Ссылка на регистрацию: https://vk.cc/cLY8ET

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21
🧠 Как не словить LazyInitializationException в Spring Boot + Hibernate

Одна из самых частых ошибок при работе с JPA:


org.hibernate.LazyInitializationException: failed to lazily initialize a collection


📌 Причина: лениво загружаемая коллекция (LAZY) обращается к БД вне транзакции — например, в слое контроллера или после закрытия Session.

💡 Как избежать?

Решение 1: @Transactional в сервисе

Убедитесь, что вы обращаетесь к ленивым коллекциям внутри метода с @Transactional:


@Transactional
public UserDto getUser(Long id) {
User user = userRepository.findById(id)
.orElseThrow();

// OK: коллекция friends будет инициализирована в транзакции
return new UserDto(user.getName(), user.getFriends());
}


⚠️ Не используйте @Transactional в контроллерах — это плохая практика.



Решение 2: Fetch Join

Подгрузите нужные данные сразу через JOIN FETCH:


@Query("SELECT u FROM User u LEFT JOIN FETCH u.friends WHERE u.id = :id")
Optional<User> findByIdWithFriends(@Param("id") Long id);


📌 Плюс: 1 запрос вместо N (N+1 проблема решается).
📌 Минус: может быть избыточная загрузка, особенно с большими коллекциями.



Решение 3: DTO проекция

Лучший способ в большинстве случаев — проецировать сразу в DTO:


@Query("""
SELECT new com.example.UserDto(u.name, f.name)
FROM User u
LEFT JOIN u.friends f
WHERE u.id = :id
""")
List<UserDto> findUserWithFriendNames(@Param("id") Long id);


📌 Выгружает только нужные данные. Быстро, безопасно, эффективно.


💬 Ленивая инициализация — ок, если вы контролируете границы транзакций.
Проекции и fetch join — ваши лучшие друзья, если нужен контроль и производительность.

👉@BookJava
👍5
🔥 Java и производительность — новая тема от онлайн-конференции Podlodka Java Crew

С 26 по 30 мая вас ждет тематическая неделя, посвящённая продвинутым практикам оптимизации Java-приложений.

В программе:

— Доклад Владимира Плизги (Tibbo System) о подходах к профилированию и инструментах, которые действительно работают;

— Воркшоп по JMH от Григория Кошелева (Контур) — научитесь писать микробенчмарки правильно;

— Круглый стол с Антоном Курако (Т-Банк) и Михаилом Поливахой (Spring АйО) — сравнение Spring, Micronaut, Quarkus и Kora через призму производительности;

— Опыт команды НСПК по нагрузочному тестированию в бою — расскажет Павел Митин.

А ещё — JFR, корутины, Kubernetes и десятки инсайтов из продакшена.

🎯 Неделя для тех, кто держит перформанс под контролем.

🔗 Подключайся: podlodka.io/javacrew
🧠 Трюк с @EventListener в Spring — убираем лишний @TransactionalEventListener

Когда тебе нужно обрабатывать события в рамках транзакции, мы часто пишем:


@TransactionalEventListener
public void handleEvent(MyEvent event) {
// ...
}


⚠️ Но есть нюанс: @TransactionalEventListener по умолчанию срабатывает после коммита. Иногда это не очевидно и вызывает баги, особенно если ожидаешь, что событие обработается внутри транзакции.

📌 Альтернатива: обычный @EventListener, но вместе с TransactionSynchronizationManager.

💡 Сниппет:


@Component
public class MyEventHandler {

@EventListener
public void handle(MyEvent event) {
if (TransactionSynchronizationManager.isActualTransactionActive()) {
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
// обработка события после коммита
}
}
);
} else {
// fallback: нет активной транзакции — выполняем сразу
}
}
}


📎 Плюсы:
— Лучше контроль: ты сам решаешь, когда обрабатывать (до/после/вне транзакции)
— Можно централизовать поведение через utility-метод
— Гибкость: логика обработки не зависит от аннотаций Spring'а

⚠️ Минус: чуть больше кода, но понятнее поведение.

👉@BookJava
👍9
🧠@Value vs @ConfigurationProperties — не выбирай наобум

Оба способа хороши для конфигурации, но используют их по-разному. И если ты всё ещё везде пихаешь @Value, держи краткий гайд, когда лучше что:


📌 @Value — просто, но не гибко:


@Value("${my.prop}")
private String value;


Хорошо для единичных значений
Плохо для сложных структур, списков, валидации
Трудно покрыть тестами (без TestPropertySource)
Нет биндинга по префиксу → нет группировки



📌 @ConfigurationProperties — сила и масштаб:


@ConfigurationProperties(prefix = "app.feature")
public class FeatureProperties {
private boolean enabled;
private List<String> items;
}


💡 Используй с @EnableConfigurationProperties или аннотируй как @Component

Удобно группировать и документировать
Работает с вложенными структурами, коллекциями
Поддерживает JSR-303 валидацию (@Validated)
Легче мокать в тестах
Интеграция с Spring Boot Actuator (/actuator/configprops)


⚠️ Не смешивай: не нужно тянуть @Value внутрь @ConfigurationProperties — это антипаттерн.


💬 Если конфигурация простая — @Value норм. Но как только появляется структура, коллекции, логика — всегда используй @ConfigurationProperties.

👉@BookJava
👍81
🚀 Открой для себя идеальный путь к лидерству с карьерным тестом от ОЭЗ «Алабуга»! 🌟

Мечтаете о карьере в крупной компании, где ваш потенциал раскроется на полную? Наш тест поможет вам определить вашу уникальную лидерскую роль. Может быть, именно вы станете тем лидером, который выведет команду на новый уровень?

После прохождения теста вы можете заполнить заявку и получить приглашение на эксклюзивную лидерскую программу. Участие в программе открывает реальные перспективы трудоустройства в ОЭЗ «Алабуга», предоставляя шанс начать путь к профессиональному признанию.

Сделайте первый шаг к своему будущему сегодня! Пройдите тест, подайте заявку и начните строить свою карьеру вместе с нами. 🎯
1👍1🍾1