Одной из часто обсуждаемых тем на собеседованиях по Spring Data JPA является проблема N+1 и возможные способы её решения. Многие отвечают, что её можно решить с помощью
join fetch
или @EntityGraph
. Однако это не всегда так.Оба подхода действительно помогают, но только в простых случаях, когда нужно выбрать все записи из базы данных, как в следующих примерах:
@Query("""
select distinct a
from Author a
left join fetch a.books
""")
List<Author> findAllFetch();
@EntityGraph(attributePaths = {"books"})
@Query("""
select distinct a
from Author a
""")
List<Author> findAllFetch();
Но что если нужно выбрать только часть данных, например, постранично? Тогда запросы будут выглядеть так:
@Query("""
select a
from Author a
left join fetch a.books
""")
Slice<Author> findAllFetch(Pageable page);
@EntityGraph(attributePaths = {"books"})
@Query("""
select distinct a
from Author a
""")
List<Author> findAllFetch(Pageable page);
Проблема в том, что когда мы используем
Pageable
, Hibernate сначала загрузит все записи в память, а затем отсортирует их. Это может привести к OutOfMemoryError
и/или серьёзной деградации производительности.В защиту Hibernate отметим, что столь неоптимизированное действие он не станет выполнять "втихую" и выведет следующий warning в логах:
WARN: HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
Более того, указав следующее свойство в
application.properties/yaml
, Hibernate и вовсе начнёт падать с JpaSystemException
:
spring.jpa.properties.hibernate.query.fail_on_pagination_over_collection_fetch=true
Как же на самом деле стоит решать проблему N+1?
Правильное решение — использование аннотации
@BatchSize
:
@Entity
public class Owner extends Person {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
@BatchSize(size = 50)
private List<Pet> pets = new ArrayList<>();
}
Если коллекций много, можно настроить глобальный размер выборки в файле
application.properties/yaml
:
spring.jpa.properties.hibernate.default_batch_fetch_size=50
С использованием
@BatchSize
или глобального свойства запросы можно переписать следующим образом:
@Query("""
select a
from Author a
""")
Slice<Author> findAllFetch(Pageable page);
List<Author> findAll(Pageable pageable);
Вывод
Используйте
@BatchSize
или spring.jpa.properties.hibernate.default_batch_fetch_size
, чтобы избежать проблемы N+1 без загрузки избыточного количества данных в память. Стоит отметить, что используя этот подход важно помнить про необходимость обращения к элементам связанной коллекции в условиях наличия открытой транзакции, чтобы Hibernate смог загрузить необходимые данные. Несмотря на то, что
spring.jpa.open-in-view=true
позволяет нам быть уверенными в наличии открытой транзакции, он не является рекомендуемым.Для более глубокого понимания оптимизации запросов рекомендуем ознакомиться с докладом экспертов сообщества Spring АйО – Ильи и Фёдора Сазоновых, с которым они выступали на последнем JPoint.
#SpringTips #JPA #DB
Please open Telegram to view this post
VIEW IN TELEGRAM
Spring Boot 3.3 раскрывает потенциал CDS (Class Data Sharing) благодаря двум новым функциям: самораспаковывающийся исполняемый JAR и поддержка Buildpacks CDS.
Команда Spring АйО перевела статью, в которой рассмотрены новые функции, нюансы их использования, а также их влияние на время запуска приложения.
Please open Telegram to view this post
VIEW IN TELEGRAM
Команда Spring АйО рада поделиться с вами свежей новостью от JetBrains: стала доступна первая EAP-версия IntelliJ IDEA 2024.3.
Среди нововведений:
🤖 Прокаченный AI Assistant
Please open Telegram to view this post
VIEW IN TELEGRAM
📖 Бесплатные книги по SRE
Google выпустила серию книг по SRE, которые могут помочь тем, кто интересуется эксплуатацией и поддержкой современных приложений. В них содержатся теория и практические рекомендации, основанные на опыте инженеров Google.
- Building Secure & Reliable Systems: о важности безопасности в обеспечении надежности систем
- The Site Reliability Workbook: примеры применения принципов и практик SRE на практике
- Site Reliability Engineering: о пользе SRE на всех этапах жизненного цикла программного обеспечения
🔗 Прочитать книги бесплатно можно тут: https://sre.google/books/
Google выпустила серию книг по SRE, которые могут помочь тем, кто интересуется эксплуатацией и поддержкой современных приложений. В них содержатся теория и практические рекомендации, основанные на опыте инженеров Google.
- Building Secure & Reliable Systems: о важности безопасности в обеспечении надежности систем
- The Site Reliability Workbook: примеры применения принципов и практик SRE на практике
- Site Reliability Engineering: о пользе SRE на всех этапах жизненного цикла программного обеспечения
🔗 Прочитать книги бесплатно можно тут: https://sre.google/books/
Почти 15 лет назад небольшая команда инженеров JetBrains приступила к, казалось бы, безумному начинанию — создать свой собственный язык программирования и добиться с ним успеха. В начале 2010-х годов Java был одним из самых популярных языков, которым пользовались миллионы инженеров. Но он не получал никаких серьезных обновлений в течение нескольких лет, и в нем не было новых функций. Разработчики искали новые решения.
Многие инженеры пытались предоставить альтернативу Java, создавая новые языки для JVM. Это стало небольшим окном возможностей для создания инструмента, который мог бы повлиять на всю отрасль. Так началась история Kotlin. Что привело к успеху Kotlin и чего это стоило команде? В этом документальном фильме вы услышите историю из первых уст.
Please open Telegram to view this post
VIEW IN TELEGRAM
Для тех, кто был слишком занят на неделе или просто пропустил некоторые посты, публикуем дайджест!
– Что нового в Java 23? — что нас ждет новое, а что станет deprecated в Java 23
– Плагины в IntelliJ IDEA – всё! — у пользователей с российскими IP-адрессами перестали устанавливаться плагины из официального маркетплейса JetBrains
– Структурное логирование в Spring Boot 3.4 — про основные шаги для настройки и использования логирования в Spring Boot 3.4
– Spring Data JPA: Проблема N+1 и один из способов её решения — один из самых часто задаваемых вопросов - проблема N+1, а также про способы её решения
– Поддержка CDS в Spring Boot и ожидания от Project Leyden — о нововведениях Spring Boot 3.3, которые раскрывают потенциал CDS
– IntelliJ IDEA 2024.3 EAP: Новые Возможности и Улучшения — о новых возможностях в будущей мажорной версии IntelliJ IDEA 2024.3
– Бесплатные книги по SRE — серия книг от Google про техническое обеспечение надёжности сайтов
– Beyond The Success Of Kotlin / Документальный фильм от EngX — в новом документальном фильме узнали, что привело к успеху Kotlin и чего это стоило команде
Please open Telegram to view this post
VIEW IN TELEGRAM
В рамках разработки приложений часто возникает необходимость в создании нескольких окружений. Например, окружение для продакшена и девелопмента. Эти окружения могут отличаться по конфигурациям, инструментам и сервисам, необходимым для работы.
Предположим, что мы хотим разработать окружения для Spring Boot приложения, использующего PostgreSQL и Kafka:
* Для продакшена: минимальный набор сервисов – Spring Boot, PostgreSQL и Kafka.
* Для разработки: расширенный набор, Spring Boot, PostgreSQL, Kafka и удобные инструменты для работы, такие как pgAdmin и KafkaUI.
Мы рассмотрим решение этой задачи в контексте использования Docker Compose. Отметим, что в большинстве случаев для продакшена рекомендуется использовать более продвинутые решения, например, Kubernetes.
Возможные способы решения поставленной задачи
1. Один файл с профилями
Можно описать все сервисы в одном
docker-compose.yml
и использовать профили для разделения сервисов, необходимых в продакшене и разработке. Такой подход позволит легко управлять сервисами, активируя нужные профили в зависимости от окружения.Преимущества:
* Один файл для управления всеми сервисами.
* Легкость переключения между окружениями за счёт использования профилей.
Недостатки:
* Отсутствие гибкости: сложно настроить разные порты, скрипты инициализации для сервисов в разных окружениях.
* Не всегда удобен для сложных конфигураций.
2. Дублирование файлов
Преимущества:
* Полная гибкость в настройке каждого окружения.
* Можно легко добавить уникальные параметры и сервисы для каждого случая.
Недостатки:
* Дублирование кода.
* Сложность синхронизации изменений между файлами.
* Проблемы с поддержкой нескольких файлов (например, при добавлении нового сервиса).
3. Переиспользование сервисов с include и extends
Возможно, не все знают, но Docker Compose предоставляет ключевые слова include и extends, которые могут отлично подойти для нашей задачи. Эти конструкции позволяют избежать дублирования кода, переиспользуя общие сервисы между различными файлами.
*
Include
даёт возможность подключить один docker compose файл к другому, аналогично запуску нескольких файлов через терминал. Этот способ полезен, если нам нужно просто включить сервисы без дополнительных изменений.*
Extends
– более гибкий инструмент, который позволяет подключить сервисы из одного файла в другой и переопределить их свойства, что особенно удобно, если требуется настроить окружение под разные нужды.Преимущества:
* Избегаем дублирования кода.
* Гибкость при настройке сервисов в разных окружениях.
* Возможность вынести общие сервисы в отдельный файл и изменять их конфигурации в каждом окружении.
Недостатки:
* Сложнее в реализации и поддержке по сравнению с одним файлом с профилями.
* Потребуются дополнительные знания о синтаксисе docker-compose.
services.yml (общие сервисы)
version: '3.8'
services:
postgres:
image: postgres:13
kafka:
image: bitnami/kafka:latest
docker-compose.prod.yml:
version: '3.8'
services:
spring:
image: my-spring-app:latest
postgres:
extends:
file: services.yml
service: postgres
kafka:
extends:
file: services.yml
service: kafka
docker-compose.dev.yml:
version: '3.8'
services:
postgres:
extends:
file: services.yml
service: postgres
kafka:
extends:
file: services.yml
service: kafka
pgadmin:
image: dpage/pgadmin4
kafka-ui:
image: provectuslabs/kafka-ui
Таким образом,
extends
позволяет нам гибко конфигурировать окружения и при этом не дублировать код, что делает этот способ наиболее подходящим для нашей задачи.Ставь ❤️ если знал про extends/include и 🔥 если не знал
#DockerCompose #Tips
Please open Telegram to view this post
VIEW IN TELEGRAM
Уже через 7 часов на YouTube канале Java пройдет прямая трансляция, посвящённая релизу Java под номером 23.
Расписание трансляции (время GMT+3 МСК):
Deep Dive into Java 23's Features!
16:00: Welcome and event agenda
16:05: Java Language Update by Gavin Bierman
16:20: Java Language Features in Action
16:35: Integrity by Default with Ron Pressler
16:55: Markdown Documentation Comments with Jonathan Gibbons
17:10: ZGC: Generational Mode by Default with Stefan Karlson
Java Outreach in 2024
17:25: Java Playground Updates with Denys Makogon and Heather Stephens
17:40: Java Community Report from Sharat Chander and Jim Grisanzio
Java Preview Features and Future work
18:10: Sneak Peek at GraalVM Updates with Alina Yurenko and Fabio Niephaus
18:30: Class-File API with Brian Goetz
18:45: State of Project Leyden with John Rose
18:15: Enjoy Your Evening!
Также про JEP'ы, включенные в этот релиз, компания JetBrains записала целую серию видео. Смотреть можно здесь:
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Java 23 - Launch Stream
Come celebrate the #Java 23 launch with us on September 17th from 13:00 to 16:30 UTC. We will cover new features, community updates, and what to expect from future releases. We'll have presentations from exciting guests like Brian Goetz, Ron Pressler, Gavin…
Netflix перешел с G1 на Generational ZGC, начиная с JDK 21, из-за значительных преимуществ, связанных с многопоточной сборкой мусора.
Команда Spring АйО подготовила перевод статьи, в которой инженеры стримингового сервиса рассказали о неожиданных и ожидаемых преимуществах Generational ZGC.
Please open Telegram to view this post
VIEW IN TELEGRAM
🌳 JPA Entity Graph и нюансы его использования
Entity Graph — это один из мощных инструментов JPA, который помогает разработчикам гибко управлять загрузкой связанных сущностей. Entity Graph позволяет динамически настраивать загрузку данных во время выполнения программы, что делает его особенно полезным в проектах со сложными структурами данных.
Команда Spring АйО подготовила статью, в которой рассмотрела, как использовать Entity Graph.
📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/844336/
#SpringTips #JPA
Entity Graph — это один из мощных инструментов JPA, который помогает разработчикам гибко управлять загрузкой связанных сущностей. Entity Graph позволяет динамически настраивать загрузку данных во время выполнения программы, что делает его особенно полезным в проектах со сложными структурами данных.
Команда Spring АйО подготовила статью, в которой рассмотрела, как использовать Entity Graph.
📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/844336/
#SpringTips #JPA
Какой технологией пользуетесь для взаимодействия с базой данных в продакшн-среде?
Anonymous Poll
74%
Spring Data JPA
19%
Spring Data JDBC/R2DBC
7%
Spring Data MongoDB/Reactive MongoDB
11%
Spring Data Redis/Reactive Redis
2%
Spring Data Cassandra/Reactive Cassandra
4%
Spring Data Elasticsearch
27%
Spring JDBC
4%
Spring MyBatis Framework
11%
JOOQ
4%
Свой вариант напишу в комментариях
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Для тех, кто был слишком занят на неделе или просто пропустил некоторые посты, публикуем дайджест!
– Эффективное управление окружениями с Docker Compose — рассказали про не всем известный способ настройки окружения с использованием extends и include
– Java 23 - Launch Stream — Oracle в прямом эфире представил Java 23 и все её нововведения
– Подчини паузы своей воле с Generational ZGC — узнали от команды Netflix о неожиданных и ожидаемых преимуществах Generational ZGC
– JPA Entity Graph и нюансы его использования — погрузились в технологию гибкого переключения между стратегиями загрузки данных
– Какой технологией пользуетесь для взаимодействия с базой данных в продакшн-среде? — провели опрос среди участников сообщества, который вызвал не мало обсуждений в комментариях
Please open Telegram to view this post
VIEW IN TELEGRAM
Друзья, хотим поделиться с вами важной новостью. Сообщество Spring АйО активно начало свою деятельность в начале лета, и, за этот, казалось бы, небольшой промежуток времени, мы успели сделать многое:
– Опубликовано 34 статьи на Хабре
– Общее количество постов в нашем канале превысило 200
– Сообщество насчитывает более 3 000 участников
Самое главное, нам удалось собрать отличную команду, которая занимается созданием материалов. Некоторых экспертов сообщества вы уже хорошо знаете, с другими мы вас ещё познакомим, а кто-то предпочитает помогать без личного упоминания.
Мы стремимся быть максимально прозрачными с вами и хотим отметить, что для производства качественного контента и поддержки команды необходимы финансовые ресурсы. Вы могли заметить, что в нашем сообществе отсутствует прямая реклама. Вместо этого мы выбрали путь сотрудничества с крупными технологическими компаниями на взаимовыгодных условиях.
В ближайшее время мы объявим всех партнёров сообщества, благодаря которым возможна стабильная работа команды Spring АйО. Вместо рекламы мы будем время от времени публиковать партнёрские посты, которые будут отмечены эмодзи –
–––
Встречайте нашего первого партнёра – компанию Haulmont. Haulmont – российская компания, специализирующаяся на разработке корпоративного программного обеспечения для коммерческого сектора и государственных структур. Для нас, как для Spring-разработчиков, Haulmont интересен таким продуктом, как Amplicode. Отметим, что команда Amplicode активно помогает нам в создании материалов и приглашает нас принимать участие в своих мероприятиях, за что им отдельное спасибо!
Благодаря поддержке наших партнёров, мы сможем продолжать развивать сообщество и создавать для вас качественный контент
Please open Telegram to view this post
VIEW IN TELEGRAM
🪲 Взлом JVM-приложения с помощью отладчика IntelliJ IDEA
Что если мы скажем вам, что отладчик может стать не просто инструментом для поиска ошибок, а настоящим "режимом бога" в мире кода?
В новом переводе от команды Spring АйО рассматривается, как можно исследовать память приложения и изменить его функциональность, при этом не затрагивая исходного кода, а используя только лишь отладчик IntelliJ IDEA.
📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/845554/
Что если мы скажем вам, что отладчик может стать не просто инструментом для поиска ошибок, а настоящим "режимом бога" в мире кода?
В новом переводе от команды Spring АйО рассматривается, как можно исследовать память приложения и изменить его функциональность, при этом не затрагивая исходного кода, а используя только лишь отладчик IntelliJ IDEA.
📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/845554/