🔥 Как настроить Spring Batch для массовой обработки данных
Spring Batch — это framework для пакетной обработки. Задачи извлечения, преобразования и загрузки данных, массовая обработка транзакций, запланированные задания с порционной обработкой, механизмами перезапуска и повторных попыток.
Обрабатывает миллионы записей эффективно, поддерживает транзакции, откат изменений, логику пропуска, параллельную обработку и интеграцию с различными источниками данных.
1️⃣ Добавляем зависимости
Базовая зависимость spring-boot-starter-batch. Для хранения metadata (job execution, step execution) нужна БД — добавьте spring-boot-starter-jdbc и драйвер БД.
Для планирования добавьте spring-boot-starter-quartz или используйте встроенный @Scheduled. Spring Batch требует БД для отслеживания состояния заданий даже для простых случаев.
2️⃣ Настраиваем Job Configuration
Аннотируйте конфиг @Configuration и @EnableBatchProcessing. Создайте Job bean через JobBuilder с одним или несколькими Steps.
Job состоит из шагов, выполняемых последовательно. Каждый шаг может быть tasklet (одна операция) или chunk-oriented (чтение-обработка-запись порциями). Используйте JobRepository для сохранения метаданных выполнения.
3️⃣ Реализуем Chunk Processing
Chunk processing разбивает работу на блоки (chunks) для транзакций. Определите ItemReader для чтения данных, ItemProcessor для обработки, ItemWriter для записи.
Настройте chunk size (количество записей в транзакции). Оптимальный размер 50-500 в зависимости от сложности обработки. Большие chunks = меньше транзакций, но больше памяти и риск rollback больших объёмов.
4️⃣ Создаём ItemReader для различных источников
Spring Batch предоставляет готовые readers: JdbcCursorItemReader (streaming из БД), JdbcPagingItemReader (пагинация), FlatFileItemReader (CSV), JsonItemReader, MongoItemReader.
Для custom источников реализуйте ItemReader<T> интерфейс с методом read(). Возвращайте null когда данные закончились. Reader должен быть stateful и thread-safe.
5️⃣ Реализуем ItemProcessor и ItemWriter
ItemProcessor<I, O> трансформирует данные. Возвращайте null для фильтрации записей (они будут пропущены). Это место для валидации, обогащения данных, вызовов внешних API.
ItemWriter<T> записывает batch данных. Используйте JdbcBatchItemWriter для bulk insert в БД, JmsItemWriter для очередей, CompositeItemWriter для записи в несколько мест одновременно.
6️⃣ Обработка ошибок и retry логика
Настройте skip policy через faultTolerant().skip(Exception.class).skipLimit(10) для пропуска проблемных записей. Логируйте пропущенные элементы через SkipListener.
Для retry настройте retry(Exception.class).retryLimit(3) с exponential backoff. Используйте ItemProcessListener и ItemWriteListener для логирования ошибок и успешных обработок.
✔️ Что происходит под капотом
JobLauncher создаёт JobExecution и сохраняет в BATCH_JOB_EXECUTION таблице. Шаг начинает выполнение: ItemReader читает chunk_size записей, ItemProcessor обрабатывает каждую, ItemWriter записывает весь chunk.
Транзакция commit'ится после успешной записи chunk. При ошибке транзакция rollback, job может повториться или скипнуться. После завершения job Spring Batch обновляет статус в БД. Это позволяет перезапускать упавшие задачт с места падения.
💡 Бонус-совет
Используйте @BeforeStep и @AfterStep аннотации на методах listener'ов для pre/post processing логики. Для сложных сценариев используйте JobExecutionDecider для динамического выбора следующего шага на основе результатов предыдущего.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
Spring Batch — это framework для пакетной обработки. Задачи извлечения, преобразования и загрузки данных, массовая обработка транзакций, запланированные задания с порционной обработкой, механизмами перезапуска и повторных попыток.
Обрабатывает миллионы записей эффективно, поддерживает транзакции, откат изменений, логику пропуска, параллельную обработку и интеграцию с различными источниками данных.
Базовая зависимость spring-boot-starter-batch. Для хранения metadata (job execution, step execution) нужна БД — добавьте spring-boot-starter-jdbc и драйвер БД.
Для планирования добавьте spring-boot-starter-quartz или используйте встроенный @Scheduled. Spring Batch требует БД для отслеживания состояния заданий даже для простых случаев.
Аннотируйте конфиг @Configuration и @EnableBatchProcessing. Создайте Job bean через JobBuilder с одним или несколькими Steps.
Job состоит из шагов, выполняемых последовательно. Каждый шаг может быть tasklet (одна операция) или chunk-oriented (чтение-обработка-запись порциями). Используйте JobRepository для сохранения метаданных выполнения.
Chunk processing разбивает работу на блоки (chunks) для транзакций. Определите ItemReader для чтения данных, ItemProcessor для обработки, ItemWriter для записи.
Настройте chunk size (количество записей в транзакции). Оптимальный размер 50-500 в зависимости от сложности обработки. Большие chunks = меньше транзакций, но больше памяти и риск rollback больших объёмов.
Spring Batch предоставляет готовые readers: JdbcCursorItemReader (streaming из БД), JdbcPagingItemReader (пагинация), FlatFileItemReader (CSV), JsonItemReader, MongoItemReader.
Для custom источников реализуйте ItemReader<T> интерфейс с методом read(). Возвращайте null когда данные закончились. Reader должен быть stateful и thread-safe.
ItemProcessor<I, O> трансформирует данные. Возвращайте null для фильтрации записей (они будут пропущены). Это место для валидации, обогащения данных, вызовов внешних API.
ItemWriter<T> записывает batch данных. Используйте JdbcBatchItemWriter для bulk insert в БД, JmsItemWriter для очередей, CompositeItemWriter для записи в несколько мест одновременно.
Настройте skip policy через faultTolerant().skip(Exception.class).skipLimit(10) для пропуска проблемных записей. Логируйте пропущенные элементы через SkipListener.
Для retry настройте retry(Exception.class).retryLimit(3) с exponential backoff. Используйте ItemProcessListener и ItemWriteListener для логирования ошибок и успешных обработок.
JobLauncher создаёт JobExecution и сохраняет в BATCH_JOB_EXECUTION таблице. Шаг начинает выполнение: ItemReader читает chunk_size записей, ItemProcessor обрабатывает каждую, ItemWriter записывает весь chunk.
Транзакция commit'ится после успешной записи chunk. При ошибке транзакция rollback, job может повториться или скипнуться. После завершения job Spring Batch обновляет статус в БД. Это позволяет перезапускать упавшие задачт с места падения.
Используйте @BeforeStep и @AfterStep аннотации на методах listener'ов для pre/post processing логики. Для сложных сценариев используйте JobExecutionDecider для динамического выбора следующего шага на основе результатов предыдущего.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥3❤1👏1
Forwarded from Библиотека задач по Java | тесты, код, задания
Какой паттерн позволяет добавлять новую функциональность объектам динамически, оборачивая их в объекты без изменения исходного кода?
Anonymous Quiz
28%
Proxy
52%
Decorator
12%
Adapter
4%
Composite
5%
Посмотреть ответ
👍6🤔4🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁29🔥3💯1
Java Developer (XWiki, Knowledge Base / FAQ) — удалёнка
Middle+ Java Engineer Keycloak (Medtech) — до 345 000 ₽ — удалёнка
TechLead / Senior Java-разработчик backend (монолит) — от 300 000 до 400 000 ₽ — гибрид (Москва)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1👏1
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥4😁2🤔1
Устали от того, что Copilot и JetBrains AI Assistant — это чёрные ящики с непонятными тарифами? Есть альтернатива.
Continue — open source плагин (Apache 2.0) для IntelliJ-based IDE, который даёт полный контроль над AI-помощником:
→ Выбираете модель сами: GPT-4, Claude, локальный Ollama
→ Контролируете, куда уходит код — можете поднять модель локально или выбрать проверенного провайдера
→ Настраиваете под команду через config.json
Что умеет
▪️ Автодополнение с контекстом проекта (не просто строка, а весь файл)
▪️ Чат, который понимает архитектуру — спроси про конкретный класс
▪️ Команды над выделенным кодом: рефакторинг, генерация тестов, упрощение
▪️ Агентный режим — Continue + MCP инструменты собирают патч сразу в нескольких файлах
Подводные камни
▪️ Качество = модель + контекст. Дешёвая LLM даст поверхностный код
▪️ Любой AI-код требует ревью. YOLO — не метод
▪️ Облачные провайдеры = риск утечки. Выбирайте осознанно
Continue превращает IDE в персонализированный инструмент, а не в терминал к чужому облаку. Особенно актуально для команд с требованиями к приватности и гибкости стека.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2❤1🌚1
Media is too big
VIEW IN TELEGRAM
Навигация по Java-классам без IntelliJ IDEA
Enterprise-проекты на Java славятся развесистой иерархией классов и глубоким наследованием. Ревьюить такой код в браузере обычно больно: не видно типов, сигнатур методов и связей между объектами.
SourceCraft решает задачу с помощью серверной индексации. В пулл-реквесте работают привычные переходы к декларациям (Go to Declaration) и поиск использований (Find Usages). Система анализирует связи непосредственно в исходном коде, избавляя от необходимости ждать, пока локальная IDE проиндексирует гигабайты файлов.
Испытайте инструмент в действии → https://sourcecraft.dev/code-navigation-demo/uikit/pr/2040
Enterprise-проекты на Java славятся развесистой иерархией классов и глубоким наследованием. Ревьюить такой код в браузере обычно больно: не видно типов, сигнатур методов и связей между объектами.
SourceCraft решает задачу с помощью серверной индексации. В пулл-реквесте работают привычные переходы к декларациям (Go to Declaration) и поиск использований (Find Usages). Система анализирует связи непосредственно в исходном коде, избавляя от необходимости ждать, пока локальная IDE проиндексирует гигабайты файлов.
Испытайте инструмент в действии → https://sourcecraft.dev/code-navigation-demo/uikit/pr/2040
❤3
List.of() появился в Java 9 и произвёл революцию в создании коллекций. Но под капотом это не просто обёртка над ArrayList — это целая иерархия оптимизированных классов.
📦 Сигнатура и варианты
Java предоставляет 12 перегруженных методов:
// Специализированные версии для 0-10 элементов
static <E> List<E> of()
static <E> List<E> of(E e1)
static <E> List<E> of(E e1, E e2)
// ... до 10 параметров
static <E> List<E> of(E e1, E e2, ..., E e10)
// Varargs для 11+ элементов
static <E> List<E> of(E... elements)
Зачем столько перегрузок?
— Избежать overhead создания varargs массива
— Каждая перегрузка возвращает оптимизированный класс
— Специализация для частых случаев (1-2 элемента)
→ Разные классы для разного размера:
// 0 элементов — singleton
static <E> List<E> of() {
return ImmutableCollections.EMPTY_LIST; // Переиспользуется!
}
// 1 элемент — List12 (List of 1 or 2)
static <E> List<E> of(E e1) {
return new ImmutableCollections.List12<>(e1);
}
// 2 элемента — тот же List12
static <E> List<E> of(E e1, E e2) {
return new ImmutableCollections.List12<>(e1, e2);
}
// 3+ элементов — ListN
static <E> List<E> of(E e1, E e2, E e3) {
return ImmutableCollections.listFromTrustedArray(e1, e2, e3);
}
→ Структура List12 (для 1-2 элементов):
static final class List12<E> extends AbstractImmutableList<E> {
private final E e0; // Всегда присутствует
private final E e1; // null если один элемент
List12(E e0) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = null;
}
List12(E e0, E e1) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = Objects.requireNonNull(e1);
}
public int size() {
return e1 != null ? 2 : 1;
}
public E get(int index) {
if (index == 0) return e0;
else if (index == 1 && e1 != null) return e1;
throw new IndexOutOfBoundsException();
}
}→ Структура ListN (для 3+ элементов):
static final class ListN<E> extends AbstractImmutableList<E> {
private final E[] elements; // Хранит все элементы
ListN(E... elements) {
// Копирование + null-check каждого элемента
this.elements = elements.clone();
for (E e : this.elements) {
Objects.requireNonNull(e);
}
}
public int size() {
return elements.length;
}
public E get(int index) {
return elements[index];
}
}1. Null элементы запрещены.
2. Varargs создаёт массив.
3. Не Serializable.
4. SubList тоже immutable.
📊 Performance бенчмарк
→ Создание списка из 3 элементов:
List.of("A", "B", "C"): ~5 ns
Arrays.asList("A", "B", "C"): ~8 ns
new ArrayList<>(Arrays.asList(...)): ~25 ns
List.of() в 5 раз быстрее ArrayList!→ Memory footprint:
List.of(1, 2, 3): 48 байт
Arrays.asList(1, 2, 3): ~72 байт (backing array + wrapper)
new ArrayList<>(3 items): ~112 байт (default capacity 10)
List.of() в 2.3 раза компактнее!
🔗 Документация
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤2🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁28👍2🔥1
🎓 Твой опыт стоит дорого — стань экспертом Proglib Academy
Чувствуешь, что накопил достаточно знаний, чтобы делиться ими с другими?
Мы ищем сильных практиков, которые хотят попробовать себя в роли:
— преподавателей;
— авторов курсов;
— наставников.
Это возможность не только монетизировать экспертизу, но и прокачать личный бренд, структурировать собственные знания и вырастить новое поколение специалистов.
👉 Заполни короткую анкету
Чувствуешь, что накопил достаточно знаний, чтобы делиться ими с другими?
Мы ищем сильных практиков, которые хотят попробовать себя в роли:
— преподавателей;
— авторов курсов;
— наставников.
Это возможность не только монетизировать экспертизу, но и прокачать личный бренд, структурировать собственные знания и вырастить новое поколение специалистов.
👉 Заполни короткую анкету
Java в мире AI: Наблюдатель или Архитектор?
Пока ML-инженеры пишут на Python, Java-разработчики интегрируют это в Enterprise. Чтобы делать это грамотно в 2026 году, нужно понимать архитектуру AI-агентов.
Мы обновили курс «Разработка AI-агентов». Теперь это не просто «курсик про ChatGPT», а системное обучение архитектуре.
Enterprise-level подход:
— Structure: 13 модулей, 2 трека (Overview для архитекторов/лидов, Advanced для разработчиков).
— Integration: Протоколы MCP, A2A, безопасный деплой.
— Security: DLP-политики, защита данных, комплаенс (критично для Java-мира).
Вы поймете, как встроить «умные» модули в ваши надежные бэкенды.
☕ Предложение 3 в 1:
Оплачиваете курс по агентам — получаете два курса в подарок. Идеально, чтобы расширить кругозор.
Ссылка
Пока ML-инженеры пишут на Python, Java-разработчики интегрируют это в Enterprise. Чтобы делать это грамотно в 2026 году, нужно понимать архитектуру AI-агентов.
Мы обновили курс «Разработка AI-агентов». Теперь это не просто «курсик про ChatGPT», а системное обучение архитектуре.
Enterprise-level подход:
— Structure: 13 модулей, 2 трека (Overview для архитекторов/лидов, Advanced для разработчиков).
— Integration: Протоколы MCP, A2A, безопасный деплой.
— Security: DLP-политики, защита данных, комплаенс (критично для Java-мира).
Вы поймете, как встроить «умные» модули в ваши надежные бэкенды.
☕ Предложение 3 в 1:
Оплачиваете курс по агентам — получаете два курса в подарок. Идеально, чтобы расширить кругозор.
Ссылка
❤3
Forwarded from Библиотека собеса по Java | вопросы с собеседований
Напишите упрощённую версию HashMap с нуля 👇
📦 Задание
Реализуйте SimpleHashMap<K, V> — собственную реализацию хеш-таблицы без использования готовых Map.
📋 Требования
1. Основная функциональность
→ put() — добавить/обновить пару ключ-значение
→ get() — получить значение по ключу (null если нет)
→ remove() — удалить элемент, вернуть старое значение
→ containsKey() — проверка наличия ключа
→ size() — текущее количество элементов
→ keySet() — множество всех ключей
2. Внутренняя структура
→ Использовать массив buckets (корзин)
→ Collision resolution через связный список (chaining)
→ Начальная ёмкость — 16 элементов
→ Load factor — 0.75
3. Обязательные фичи
→ Автоматическое расширение (resize) при превышении load factor
→ Корректная работа с null ключами
→ Правильный расчёт hashCode (учитывать equals/hashCode contract)
→ Обработка коллизий
Ставьте → 🔥, если нравится формат. Если нет → 🤔
#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍1🤔1