Sandbox
Java Sandbox
Spring Context Sandbox
Spring Web Sandbox
Spring Data JPA Sandbox
PostgreSQL Sandbox
Apache Kafka Sandbox
Other
Please open Telegram to view this post
VIEW IN TELEGRAM
👍40❤11🤯3
Developer's Sandbox pinned «🔤 🔤 🔤 🔤 Sandbox 📦 🔤 Сравнение JDBC, Spring JDBC, Hibernate, Spring Data JPA 🔤 Логирование JDBC запросов 🔤 Обзор Spring Data JDBC, MyBatis, JOOQ 🔤 Что такое Spring Boot и для чего он используется? Java Sandbox ☕️ 🔤 В чем разница между анонимным классом и λ-выражением?…»
Недавно вышла общедоступная версия Java 21, которая является следующей LTS (Long-term support) версией после Java 17
Смотрел, какие новые фичи добавили в язык и захотел поделиться с вами полезным ресурсом, где я обычно смотрю обновления — javaalmanac
Здесь можно найти информацию по каждой версии Java, начиная с первой и заканчивая той, что на данный момент в разработке (Java 22)
❓ Что тут можно найти?
— Ссылки на спецификации — языка, API, виртуальной машины
— Ссылки на release notes
— Если перейти на конкретную версию, то по каждому уровню (JVM, Language, API), можно увидеть список добавленных фич, многие из которых объясняются с примерами
— В колонке "Compare API to" можно выбрать предыдущие версии, сравнив API до самых мелочей, например, между Java 21 и Java 20 добавился метод isEmoji(int) в Character классе
Заодно решил обновить свои примеры на самые последние версии:
— Перешел на Java 21
— Отрефакторил build.gradle и перешел в нем с Groovy на Kotlin
— Обновил все версии библиотек, а где используется docker — обновил версии imag'ей
Теперь структура примеров еще проще:
🌱 sandbox-spring-context
🌱 sandbox-spring-web
📖 sandbox-kafka
☕️ sandbox-java
#note #sources
➿ Меню
➿ Подпишись: @developer_sandbox
Смотрел, какие новые фичи добавили в язык и захотел поделиться с вами полезным ресурсом, где я обычно смотрю обновления — javaalmanac
Здесь можно найти информацию по каждой версии Java, начиная с первой и заканчивая той, что на данный момент в разработке (Java 22)
— Ссылки на спецификации — языка, API, виртуальной машины
— Ссылки на release notes
— Если перейти на конкретную версию, то по каждому уровню (JVM, Language, API), можно увидеть список добавленных фич, многие из которых объясняются с примерами
— В колонке "Compare API to" можно выбрать предыдущие версии, сравнив API до самых мелочей, например, между Java 21 и Java 20 добавился метод isEmoji(int) в Character классе
Заодно решил обновить свои примеры на самые последние версии:
— Перешел на Java 21
— Отрефакторил build.gradle и перешел в нем с Groovy на Kotlin
— Обновил все версии библиотек, а где используется docker — обновил версии imag'ей
Теперь структура примеров еще проще:
#note #sources
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
Delivery semantics [delivery guarantees, processing guarantees] — это способы доставки сообщений, т.е. как именно будут взаимодействовать между собой Producer, Broker и Consumer для того чтобы доставить сообщение.
Рассмотрим на примере классической схемы. У нас есть:
Шаг 1. Producer читает данные из БД
Шаг 2. Producer отправляет сообщение Broker’y в demo.topic
Шаг 3. Broker сохраняет сообщение в demo.topic’e
Шаг 4. Broker уведомляет Producer’a, подтверждая что сообщение сохранено [acknowledgment]
Шаг 5. Consumer читает сообщение из demo.topic’a
Шаг 6. Consumer уведомляет Broker’a, что сообщение успешно прочитано [offset commit]
Шаг 7. Consumer сохраняет данные в БД
На каждом шаге может произойти сбой, например:
❌ Закончилась оперативная память — OutOfMemoryError
❌ Закончилось место на диске
❌ Временный сбой в сети
❌ Случился timeout, например, Шаг 3 — Broker слишком долго сохранял сообщение
В зависимости от того, какие гарантии мы хотим получить в случае если что-то пойдет не так, мы используем разные delivery semantics.
Delivery semantics для Producer’a:
Тут может быть ситуация, если Broker записал сообщение, но вышел из строя на этапе отправки acknowledgment’a, и когда Broker восстановится и Producer переотправит сообщение, то мы по сути создадим дубликат, сохранив в Broker’e дважды одно сообщение.
Delivery semantics для Consumer’a:
У нас Шаг 7, например, Spring приложение Consumer упало с OOM и потом поднялось, но перечитывать сообщение не будет хоть и могло бы записать что-то в БД. Тут мы теряем обработку сообщения.
У нас Шаг 6 и Шаг 7 меняются местами, однако, например, мы делаем транзакцию в БД, хотим сделать commit offset и падаем с OOM, и когда поднимаемся, то перечитываем сообщение и делаем ту же транзакцию, что может создать дубликат в БД.
Чтобы не создать дубликат и не потерять обработку сообщения у нас есть 2 варианта:
— Транзакция в БД идемпотентна и если мы повторим ее, то ничего не изменится
— Мы делаем commit offset в рамках транзакции к БД [необязательно хранить offset в Broker’e, можно хранить их в БД], чтобы Шаг 6 и Шаг 7 был одним атомарным шагом. Тогда у нас нет дубликатов и обработку сообщения мы не теряем
Немного рефакторинга —
#sandbox_kafka #spring_boot_kafka
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍7❤4
Какое количество технических собеседований у вас было?
Anonymous Poll
32%
0
38%
1-5
11%
5-10
18%
10+
Планирую выбрать новое название для канала, что думаете?
Anonymous Poll
30%
Dev Sandbox
17%
IT Sandbox
3%
Другое (предложить свой вариант в комментариях)
50%
Оставить текущее название
После продолжительного перерыва, я вернулся с новой статьей. Буду стараться писать одну/две статьи в неделю.
Давайте напишем одинаковое приложение, используя JDBC, Spring JDBC, Hibernate и Spring Data JPA. Посмотрим наглядно, как исторически повышался уровень абстракции при работе с БД в Java мире.
❓ Какое приложение напишем?
CRUD для работы с сущностью Book и ее связями — Author, Comment, Genre
Реализуем API для:
1⃣ Получения всех книг и ее связей
2⃣ Получения книги по id и ее связей
3⃣ Создания книги и ее связей
4⃣ Обновления книги и ее связей
5⃣ Удаления книги и ее комментариев и информации о жанрах
Модель данных опишем таблицами:
1⃣ books — данные о книгах
2⃣ authors — данные об авторах. С books “one-to-one”
3⃣ genres — данные о жанрах
4⃣ comments — данные о комментариях к книгам. С books “one-to-many”
5⃣ books_genres — промежуточная таблица для создания “many-to-many” между books и genres
Начнем в порядке повышения уровня абстракции:
📚 JDBC [Java Database Connectivity] — спецификация синхронного API для работы с реляционными БД из Java приложений. Входит в состав Java SE.
Реализацию API предоставляет JDBC драйвер.
Например, для PostgresSQL есть драйвер postgresql-42.6.0.jar, внутри есть класс PgResultSet, реализующий интерфейс java.sql.ResultSet из JDBC спецификации.
Для отправки SQL запроса, нужно:
1⃣ Получить Connection
2⃣ Создать Statement, передав SQL запрос в виде String
3⃣ Если это параметризованный запрос, то передать параметры через .set методы в Statement’e
4⃣ Выполнить запрос и получить ResultSet
5⃣ Разобрать ResultSet, получив из него данные для создания объектов Book, Author, Comment, Genre
6⃣ Закрыть ResultSet
7⃣ Закрыть Statement
8⃣ Закрыть Connection
Пример доступен на🐙 Github
🌱 Spring JDBC — набор абстракций, упрощяющий написание кода при работе с JDBC. Чтобы как можно меньше шагов пришлось писать самому.
Например, аннотация Transactional для механизма транзакций, класс NamedParameterJdbcOperations для выполнения запросов.
Теперь нам не нужно самостоятельно открывать Connection и закрывать его вместе с Statement и ResultSet. Однако разбирать данные из ResultSet'a все еще нужно вручную.
Пример доступен на🐙 Github
🪞 Hibernate — ORM [Object Relational Mapping] фреймворк. Реализует JPA спецификацию. Переход от реляционной парадигмы в ООП парадигму. Сама реализация для доступа к БД использует тот же JDBC.
Мы начинаем работать с таблицами из БД как с Java объектами. Убирается необходимость самостоятельного разбора ResultSet'ов. Вводится понятие HQL [в спецификации JPA называется JPQL], как универсального языка запросов, для обеспечения независимости от реализации БД.
Однако появляется N+1 проблема, и множество других подводных камней, которые нужно учесть, чтобы ORM фреймворк генерировал оптимальный SQL.
Пример доступен на🐙 Github
🌱 Spring Data JPA — часть umbrella проекта Spring Data, представляет дополнительный уровень абстракции над JPA. По-умолчанию использует Hibernate как JPA реализацию.
Благодаря абстракции Repository, позволяет генерировать запросы на основе имени метода, убирая возможность в некоторых ситуациях писать даже JPQL. Помимо этого имеет и много других возможностей, значительно ускоряя написание кода.
Содержит все те же недостатки что и Hibernate [в случае если используется именно он как реализация JPA].
Пример доступен на🐙 Github
#sandbox_java_database_tools
➿ Меню
➿ Подпишись: @developer_sandbox
Давайте напишем одинаковое приложение, используя JDBC, Spring JDBC, Hibernate и Spring Data JPA. Посмотрим наглядно, как исторически повышался уровень абстракции при работе с БД в Java мире.
CRUD для работы с сущностью Book и ее связями — Author, Comment, Genre
Реализуем API для:
Модель данных опишем таблицами:
Начнем в порядке повышения уровня абстракции:
Реализацию API предоставляет JDBC драйвер.
Например, для PostgresSQL есть драйвер postgresql-42.6.0.jar, внутри есть класс PgResultSet, реализующий интерфейс java.sql.ResultSet из JDBC спецификации.
Для отправки SQL запроса, нужно:
Пример доступен на
Например, аннотация Transactional для механизма транзакций, класс NamedParameterJdbcOperations для выполнения запросов.
Теперь нам не нужно самостоятельно открывать Connection и закрывать его вместе с Statement и ResultSet. Однако разбирать данные из ResultSet'a все еще нужно вручную.
Пример доступен на
Мы начинаем работать с таблицами из БД как с Java объектами. Убирается необходимость самостоятельного разбора ResultSet'ов. Вводится понятие HQL [в спецификации JPA называется JPQL], как универсального языка запросов, для обеспечения независимости от реализации БД.
Однако появляется N+1 проблема, и множество других подводных камней, которые нужно учесть, чтобы ORM фреймворк генерировал оптимальный SQL.
Пример доступен на
Благодаря абстракции Repository, позволяет генерировать запросы на основе имени метода, убирая возможность в некоторых ситуациях писать даже JPQL. Помимо этого имеет и много других возможностей, значительно ускоряя написание кода.
Содержит все те же недостатки что и Hibernate [в случае если используется именно он как реализация JPA].
Пример доступен на
#sandbox_java_database_tools
Please open Telegram to view this post
VIEW IN TELEGRAM
❤26🔥10👍6
Хотел написать в одной статье о типах связей в реляционных БД, и как их реализовать в JPA
Однако в одну статью с примерами кода не поместилось, поэтому разделил на две статьи и создал отдельные репозитории:
🐘 sandbox-postgresql
🌱 sandbox-spring-data-jpa
Если в статье SQL код неправильно отображается, нужно обновить Telegram.
❓ Какие существуют типы связей в реляционных БД?
Рассмотрим на примере нашей любимой доменной модели — Библиотеки
У нас будут две сущности — Книга, Автор
В зависимости от наших требований к системе, мы будем строить нужную связь между сущностями
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. А также, чтобы автор имел возможность написать только одну книгу.
Решение:
Для реализации такой модели данных нам подойдет отношение One to One [читается как “один автор — одна книга”]:
Здесь важно установить UNIQUE constraint, в нашем случае на поле author_id, чтобы разные книги не могли ссылаться на одного автора.
Также вместо author_id, можно сделать book_id в таблице authors, и наше требование тоже выполнится.
Таким образом мы выбираем, кто будет владельцем связи, Book или Author [об этом будет подробнее в статье про Spring Data JPA, но если кратко, тот у кого в таблице foreign key]
Пример доступен на🐙 Github
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. Однако, автор может написать сколько угодно книг.
Решение:
В этом случае нам подойдет отношение One to Many [читается как “один автор — множество книг”]
Иногда выделяют отношение Many to One [читается как “множество книг — один автор”], разницы в реализации между ними нету, мы только меняем акцент, когда говорим что с чем связано
Единственная разница в реализации между One to One и One to Many, что теперь у нас нету UNIQUE constraint для поля author_id
Также если мы сделаем book_id в таблице authors вместо author_id в таблице books, то наше требование не выполнится, потому что тогда автор сможет иметь только одну книгу
[Поэтому в JPA у аннотации ManyToOne нету параметра mappedBy, потому что такая сущность точно является владельцем связи, т.е. имеет foreign key на другую сущность]
Пример доступен на🐙 Github
Требование:
В нашей системе мы хотим чтобы у одной книги было сколько угодно авторов. А также, автор может написать сколько угодно книг.
Решение:
Здесь нам подходит Many to Many [читается как “множество авторов — множество книг”]:
Создается дополнительная таблица books_authors, указывающая нужные связи между сущностями
Не стоит также забывать о добавлении UNIQUE constraint’a на связь book_id и author_id, чтобы связь была уникальной
Пример доступен на🐙 Github
#sandbox_postgresql #relationships
➿ Меню
➿ Подпишись: @developer_sandbox
Однако в одну статью с примерами кода не поместилось, поэтому разделил на две статьи и создал отдельные репозитории:
Если в статье SQL код неправильно отображается, нужно обновить Telegram.
Рассмотрим на примере нашей любимой доменной модели — Библиотеки
У нас будут две сущности — Книга, Автор
В зависимости от наших требований к системе, мы будем строить нужную связь между сущностями
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. А также, чтобы автор имел возможность написать только одну книгу.
Решение:
Для реализации такой модели данных нам подойдет отношение One to One [читается как “один автор — одна книга”]:
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL,
author_id BIGINT NOT NULL UNIQUE REFERENCES authors (id)
);
Здесь важно установить UNIQUE constraint, в нашем случае на поле author_id, чтобы разные книги не могли ссылаться на одного автора.
Также вместо author_id, можно сделать book_id в таблице authors, и наше требование тоже выполнится.
Таким образом мы выбираем, кто будет владельцем связи, Book или Author [об этом будет подробнее в статье про Spring Data JPA, но если кратко, тот у кого в таблице foreign key]
Пример доступен на
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. Однако, автор может написать сколько угодно книг.
Решение:
В этом случае нам подойдет отношение One to Many [читается как “один автор — множество книг”]
Иногда выделяют отношение Many to One [читается как “множество книг — один автор”], разницы в реализации между ними нету, мы только меняем акцент, когда говорим что с чем связано
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL,
author_id BIGINT NOT NULL REFERENCES authors (id)
);
Единственная разница в реализации между One to One и One to Many, что теперь у нас нету UNIQUE constraint для поля author_id
Также если мы сделаем book_id в таблице authors вместо author_id в таблице books, то наше требование не выполнится, потому что тогда автор сможет иметь только одну книгу
[Поэтому в JPA у аннотации ManyToOne нету параметра mappedBy, потому что такая сущность точно является владельцем связи, т.е. имеет foreign key на другую сущность]
Пример доступен на
Требование:
В нашей системе мы хотим чтобы у одной книги было сколько угодно авторов. А также, автор может написать сколько угодно книг.
Решение:
Здесь нам подходит Many to Many [читается как “множество авторов — множество книг”]:
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL
);
CREATE TABLE books_authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
book_id BIGINT NOT NULL REFERENCES books (id),
author_id BIGINT NOT NULL REFERENCES authors (id),
UNIQUE (book_id, author_id)
);
Создается дополнительная таблица books_authors, указывающая нужные связи между сущностями
Не стоит также забывать о добавлении UNIQUE constraint’a на связь book_id и author_id, чтобы связь была уникальной
Пример доступен на
#sandbox_postgresql #relationships
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤4🔥4
При использовании ORM на этапе разработки, часто возникает необходимость посмотреть какой именно SQL запрос генерируется для отправки в БД, чтобы вовремя обнаружить ошибки и сравнить ожидаемый запрос с реальным
Желательно, чтобы параметры уже были подставлены для сгенерированного SQL запроса, чтобы можно было его скопировать и используя, например — DBeaver, DataGrip, pgAdmin, отправить и посмотреть на результат, либо более детально его проанализировать
Если добавить логгер — org.hibernate.orm.jdbc.bind: trace, то мы увидим еще и параметры, но в нужное место в запросе нам придется подставлять их самостоятельно
На картинке отображается пример логов при выполнении SQL запроса из примера на
Для получения таких, либо похожих логов, есть несколько инструментов:
#sandbox_java_database_tools
Please open Telegram to view this post
VIEW IN TELEGRAM
❤16👍11🔥4
В предыдущей статье, мы поговорили о типах связей в реляционных БД. Давайте рассмотрим их реализации в JPA, на примере нашей доменной модели — Библиотеки, где у нас есть две сущности — Author и Book
Начнем с One to One, который можно реализовать двумя способами:
// Book.class
@OneToOne
// Annotation @JoinColumn(name = "author_id", nullable = false, unique = true) can be skipped,
// because of default name mapping
private Author author;
Представим, что мы вновь работаем только с SQL. Тогда, зная id сущности Author, мы можем получить как самого автора, так и его книгу. [автора по id, а книгу по author_id].
Теперь, возвращаемся к JPA. Если у нас нету ссылки на класс Book в классе Author, то по-умолчанию, самого автора получить мы можем, а вот его книгу — нет. Чтобы исправить это, нам нужно указать связь и в классе Author:
// Author.class
/*
* One Author to One Book
* Bidirectional relationship
* Owner of the relationship is Book [because books table contains foreign key to authors table],
* linked by 'author' field in Book class
*/
@OneToOne(mappedBy = "author")
private Book book;
Таким образом, в JPA выделяют два типа связей:
При использовании Bidirectional связи, появляются дополнительные проблемы, которые необходимо учитывать, например:
❌ В методах equals, hashCode, toString, а также при сериализации можно получить java.lang.StackOverflowError
❌ Если мы меняем только unowned side, без изменения owning side, то автоматически такие изменения не будут синхронизорованы с БД
❌ Для write операций необходимо поддерживать Bidirectional setter'ы, чтобы данные оставались консистентными в БД
Unidirectional пример доступен на
Bidirectional пример доступен на
One to Many и Many to One:
// Book.class
@ManyToOne
// Annotation @JoinColumn(name = "author_id", nullable = false) can be skipped,
// because of default name mapping
private Author author;
// Author.class
/*
* One Author to Many Books
* Bidirectional relationship
* Owner of the relationship is Book [because books table contains foreign key to authors table],
* linked by 'author' field in Book class
*/
@OneToMany(mappedBy = "author")
private Set<Book> books;
Hibernate не советует использовать аннотацию OneToMany без ManyToOne, о чем упоминается в документации
Unidirectional пример доступен на
Bidirectional пример доступен на
Many to Many:
// Book.class
@ManyToMany
@JoinTable(
name = "books_authors",
joinColumns = @JoinColumn(name = "book_id", nullable = false),
inverseJoinColumns = @JoinColumn(name = "author_id", nullable = false)
)
private Set<Author> authors;
// Author.class
/*
*
* Many Authors to Many Books
* Bidirectional relationship
* Owner of the relationship is Book,
* linked by 'authors' field in Book class. If required, Author can be owner side
*/
@ManyToMany(mappedBy = "authors")
private Set<Book> books;
Если возникает необходимость добавить дополнительные колонки в таблицу со связями и использовать их, то придется создавать дополнительную Entity. Об этом случае хорошо написано в документации
Unidirectional пример доступен на
Bidirectional пример доступен на
#sandbox_spring_data_jpa #relationships
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥6❤2
Наступает 2024 год ♥️
Хочу пожелать всем успехов в Новом Году!🎄 🎁
Тем, кто ищет работу - найти ее и стать частью хорошей команды🎁
Тем, кто уже работает - профессиональных достижений и комфортных сроков🎁
Какой бы уровень знаний ни был, мы продолжаем учиться и получать новый опыт, а обмениваясь им, мы экономим время и силы друг друга✅
Благодарю вас за то, что читаете этот канал, ставите реакции и пишете комментарии!🐱
И поздравляю Вас с наступающим 2024 годом!❄️
———
Небольшая статистика:
Канал создан 14.06.2022
Первый пост я опубликовал 15.07.2023, вышло, что от идеи до начала реализации прошел год и 1 месяц
На сегодняшний день '31.12.2023', написано 28 постов и 41 пример на🐙 Github, они доступны в обновляющемся Меню
———
Обновление:
В IDEA есть Run Configurations, благодаря которым можно по одному клику настроить, что конкретно будет запускаться, и их можно сохранить в файл
Т.е. когда кто-то через IDEA откроет проект, они будут у него доступны
Я добавил их в каждый репозиторий:
📦 sandbox
☕️ sandbox-java
🌱 sandbox-spring-context
🌱 sandbox-web
🐘 sandbox-postgresql
🌱 sandbox-spring-data-jpa
📖 sandbox-kafka
Особенно это удобно для📖 sandbox-kafka, в котором, по одному клику можно запустить кластер с одним брокером, либо с двумя, либо добавить мониторинг, и еще, в дополнении к confluentinc image, добавились и другие — bitnami и wurstmeister
Хочу пожелать всем успехов в Новом Году!
Тем, кто ищет работу - найти ее и стать частью хорошей команды
Тем, кто уже работает - профессиональных достижений и комфортных сроков
Какой бы уровень знаний ни был, мы продолжаем учиться и получать новый опыт, а обмениваясь им, мы экономим время и силы друг друга
Благодарю вас за то, что читаете этот канал, ставите реакции и пишете комментарии!
И поздравляю Вас с наступающим 2024 годом!
———
Небольшая статистика:
Канал создан 14.06.2022
Первый пост я опубликовал 15.07.2023, вышло, что от идеи до начала реализации прошел год и 1 месяц
На сегодняшний день '31.12.2023', написано 28 постов и 41 пример на
———
Обновление:
В IDEA есть Run Configurations, благодаря которым можно по одному клику настроить, что конкретно будет запускаться, и их можно сохранить в файл
Т.е. когда кто-то через IDEA откроет проект, они будут у него доступны
Я добавил их в каждый репозиторий:
Особенно это удобно для
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉26🎄4☃2👍2🔥1
Новогодние праздники внесли свои коррективы и что-то "Буду стараться писать одну/две статьи в неделю" не получилось 🫠
Тем не менее, продолжим и поговорим о консольных инструментах Apache Kafka
❓ Почему именно консольных?
Есть большое количество продуктов, предоставляющих UI для Apache Kafka, среди них:
1⃣ UI for Apache Kafka, используемый в моих примерах
2⃣ AKHQ
3⃣ Confluent Control Centre
4⃣ Offset Explorer
5⃣ Kafka IDEA Plugin
Однако, судя по опыту, не всегда на проекте есть Web UI, иногда даже может не быть прямого доступа из локальной машины, а на сервере таких инструментов не будет
Помимо этого, данные инструменты умеют далеко не все, что предоставляют их консольные аналоги, а если и умеют, то платно
Поэтому переходим к консольным инструментам, а среди них:
1⃣ Kafka tools — инструменты входящие в состав самой Apache Kafka
2⃣ Kcat — предоставляет более удобный интерфейс, но требует отдельной установки
Давайте остановимся на Kafka tools, и посмотрим, какие операции мы можем выполнить:
📖 kafka-configs.sh
➖ Получить полную конфигурацию брокера/топика
➖ Добавить или обновить конфигурацию брокера/топика
➖ Удалить или сбросить до значения по умолчанию конфигурацию брокера/топика
📖 kafka-topics.sh
➖ Получить список всех топиков
➖ Получить информацию по топику
➖ Создать топик с заданной конфигурацией
➖ Увеличить топику количество партиций
➖ Удалить топик
➖ Удалить все сообщения в топике
📖 kafka-delete-records.sh
➖ Удалить сообщения в топике с самого начала до определенного offset'a
📖 kafka-console-consumer.sh
➖ Прочитать все сообщения с самого начала либо под определенной consumer-group
➖ Прочитать одно сообщение с определенной партиции и offset'a
📖 kafka-console-producer.sh
➖ Отправить сообщение с возможностью указания key,value,headers
➖ Если совместить kafka-console-consumer и kafka-console-producer, можно скопировать все сообщения из одного топика в другой [Например из DLT в основной, чтобы заново обработать сообщения]
📖 kafka-consumer-groups.sh
➖ Получить информацию о всех/одной consumer group
➖ Получить план по сбрасыванию offset'a для заданной consumer group
➖ Сбросить offset до самого начала или определенного значения для заданной consumer group
📖 kafka-log-dirs.sh
➖ Получить информацию об объеме данных в топике по каждой партиции, а также суммарно
📖 kafka-run-class.sh
➖ Получить текущий последний offset в топике
➖ Сделать partition log dump
📖 kafka-reassign-partitions.sh
➖ Сгенерировать и выполнить reassigning plan, по которому можно перераспределить партиции в кластере
📖 kafka-producer-perf-test.sh
➖ Провести нагрузочное тестирование со стороны Producer'a и получить детальный отчет
📖 kafka-consumer-perf-test.sh
➖ Провести нагрузочное тестирование со стороны Consumer'a и получить детальный отчет
И это далеко не все возможности, которые предоставляют консольные инструменты. Я привел лишь основные.
Вы можете попробовать запустить их сами, они доступны на🐙 Github, рекомендую сначала ознакомиться с quick-start.md
До новых встреч!
#sandbox_kafka #cheatsheet #console_tools
➿ Меню
➿ Подпишись: @developer_sandbox
Тем не менее, продолжим и поговорим о консольных инструментах Apache Kafka
Есть большое количество продуктов, предоставляющих UI для Apache Kafka, среди них:
Однако, судя по опыту, не всегда на проекте есть Web UI, иногда даже может не быть прямого доступа из локальной машины, а на сервере таких инструментов не будет
Помимо этого, данные инструменты умеют далеко не все, что предоставляют их консольные аналоги, а если и умеют, то платно
Поэтому переходим к консольным инструментам, а среди них:
Давайте остановимся на Kafka tools, и посмотрим, какие операции мы можем выполнить:
И это далеко не все возможности, которые предоставляют консольные инструменты. Я привел лишь основные.
Вы можете попробовать запустить их сами, они доступны на
До новых встреч!
#sandbox_kafka #cheatsheet #console_tools
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍6❤3
В прошлый раз мы рассмотрели как выглядит одно и то же приложение, при использовании технологий — JDBC, Spring JDBC, Hibernate и Spring Data JPA.
Давайте теперь добавим еще технологий — Spring Data JDBC, MyBatis, JOOQ.
🌱 Spring Data JDBC — реализация ORM фреймворка от Spring. Внутри не использует Hibernate, а отправляет запросы, используя JdbcTemplate.
Имеет свои аннотации [Id, Column, MappedColleсtion и т.д.] в пакете org.springframework.data.annotation.
Поддерживает генерацию SQL на основе имени метода в репозитории.
❓ Какие отличия от Hibernate?
— Отсутствует свой язык запросов [нет JPQL, только SQL]
— Отсутствует Lazy Loading [one-to-many отношение будет получено сразу, вместе с N+1 проблемой]
— Отсутствует кеширование [не отслеживается состояние сущности. Нужно явно вызывать методы репозитория]
— По умолчанию поддерживается только тип Identity для генерации id [поддержку Sequence, UUID нужно написать самим]
— По умолчанию нет поддержки Batch операций [поддержку можно написать через свой абстрактный репозиторий]
Основным подходом является DDD [Domain-Driven Design], и понятие Aggregate является ключевым при работе с фреймворком, например:
— Нет явной поддержки many-to-one [можно получить только id связанной сущности либо объект AggregateReference]
— Нет явной поддержки many-to-many [нужно создать отдельную сущность]
— Каскадные операции применяются только для агрегата [при обновлении агрегата, дочерние сущности пересоздаются]
Пример доступен на🐙 Github
🐦 MyBatis — persistence framework. Имеет более низкоуровневый API, чем Spring Data JDBC/JPA, но более высокоуровневый, чем JDBC/Spring JDBC.
❓ Какие основные особенности?
— В качестве сущности может использоваться POJO [Plain Old Java Object]
— Вместо Repository используется понятие Mapper [имеет свой дополнительный синтаксис при написании SQL]
— Конфигурируется с помощью XML либо аннотаций
— Имеет свой генератор кода, генерирующий простой CRUD и сами сущности на основе БД
Пример доступен на🐙 Github
💡 jOOQ [java Object Oriented Querying] — библиотека, генерирующая DSL [Domain Specific Language] для работы с SQL в формате type safe через fluent API.
❓ Какие основные особенности?
— Генерирует сущности на основе БД, а также DAO классы с набором готовых методов
— Генератор гибко настраивается [можно добавить equals, hashCode. Аннотации JPA и Spring Context и т.д.]
— По умолчанию использует стратегию именования сгенерированных классов по имени таблицы [если их назвать во множественном числе, такие классы и получим. Исправить можно через свою стратегию именования]
— Иногда совмещают с более высокоуровневыми Spring Data JDBC/JPA
Пример доступен на🐙 Github
#sandbox_java_database_tools
➿ Меню
➿ Подпишись: @developer_sandbox
Давайте теперь добавим еще технологий — Spring Data JDBC, MyBatis, JOOQ.
Имеет свои аннотации [Id, Column, MappedColleсtion и т.д.] в пакете org.springframework.data.annotation.
Поддерживает генерацию SQL на основе имени метода в репозитории.
— Отсутствует свой язык запросов [нет JPQL, только SQL]
— Отсутствует Lazy Loading [one-to-many отношение будет получено сразу, вместе с N+1 проблемой]
— Отсутствует кеширование [не отслеживается состояние сущности. Нужно явно вызывать методы репозитория]
— По умолчанию поддерживается только тип Identity для генерации id [поддержку Sequence, UUID нужно написать самим]
— По умолчанию нет поддержки Batch операций [поддержку можно написать через свой абстрактный репозиторий]
Основным подходом является DDD [Domain-Driven Design], и понятие Aggregate является ключевым при работе с фреймворком, например:
— Нет явной поддержки many-to-one [можно получить только id связанной сущности либо объект AggregateReference]
— Нет явной поддержки many-to-many [нужно создать отдельную сущность]
— Каскадные операции применяются только для агрегата [при обновлении агрегата, дочерние сущности пересоздаются]
Пример доступен на
— В качестве сущности может использоваться POJO [Plain Old Java Object]
— Вместо Repository используется понятие Mapper [имеет свой дополнительный синтаксис при написании SQL]
— Конфигурируется с помощью XML либо аннотаций
— Имеет свой генератор кода, генерирующий простой CRUD и сами сущности на основе БД
Пример доступен на
— Генерирует сущности на основе БД, а также DAO классы с набором готовых методов
— Генератор гибко настраивается [можно добавить equals, hashCode. Аннотации JPA и Spring Context и т.д.]
— По умолчанию использует стратегию именования сгенерированных классов по имени таблицы [если их назвать во множественном числе, такие классы и получим. Исправить можно через свою стратегию именования]
— Иногда совмещают с более высокоуровневыми Spring Data JDBC/JPA
Пример доступен на
#sandbox_java_database_tools
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍8❤2
Во время работы над постом я сталкиваюсь с нюансами, которые не всегда можно правильно описать в самом посте.
Например, из-за объема либо неподходящего контекста
Однако поделиться хотелось бы и для этого я создал чат, в котором планирую писать о нюансах [как что-то работает или не работает] гораздо чаще, ведь для этого не нужно готовить целый пост
❓ Как еще можно использовать чат?
— Анонсы и обсуждение будущих постов
— Можете задавать вопросы любого уровня
— Будем общаться вместе на тему разработки [можно общаться свободно, а нюансы, которые я планирую писать, буду выделять тегами, чтобы их можно было найти]
Недавно посмотрел один интересный доклад, и мой краткий пересказ со ссылкой на сам доклад как раз будут в чате
Присоединяйтесь по ссылке —📦 Developer's Chat
Например, из-за объема либо неподходящего контекста
Однако поделиться хотелось бы и для этого я создал чат, в котором планирую писать о нюансах [как что-то работает или не работает] гораздо чаще, ведь для этого не нужно готовить целый пост
— Анонсы и обсуждение будущих постов
— Можете задавать вопросы любого уровня
— Будем общаться вместе на тему разработки [можно общаться свободно, а нюансы, которые я планирую писать, буду выделять тегами, чтобы их можно было найти]
Недавно посмотрел один интересный доклад, и мой краткий пересказ со ссылкой на сам доклад как раз будут в чате
Присоединяйтесь по ссылке —
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍2
Современные приложения используют готовые библиотеки, которые необходимо конфигурировать. Код, отвечающий лишь за запуск приложения, усложняется.
Благодаря convention over configuration подходу, Spring Boot позволяет значительно упростить код. Например:
— подключив spring-boot-starter-actuator в Maven/Gradle мы получаем рабочий функционал мониторинга
— подключив flyway-core и положив файлы миграций в директорию db/migration, они будут автоматически выполнены
За счет исполнения кода автоконфигураций
Автоконфигурация — обычный бин, помеченный аннотацией Configuration или Autoconfiguration и объявленный в файле META-INF/spring.factories [до версии 2.7] или META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.import [c версии 2.7]
Библиотека, содержащая автоконфигурацию, имеет название Spring Boot Starter
Подключая в наш проект starter, фреймворк автоматически исполняет код автоконфигураций, создавая необходимые бины и исполняя логику, задуманную конкретной библиотекой
А благодаря Conditional аннотациям, такая логика может быть очень гибкой. Например:
— ConditionalOnMissingBean создаст бин, если нет другой реализации
— ConditionalOnProperty создаст бин при наличии определенного свойства в application.yaml
Spring Boot предоставляет BOM [Bill Of Materials] spring-boot-dependencies, являющийся готовым набором совместимых между собой версий библиотек
Это дает нам возможность не указывать явно версии для большого количества зависимостей в Maven/Gradle
В наших примерах по работе с БД было много повторяющегося кода. Я вынес общий код в starter и теперь все примеры реализуют один и тот же API контракт:
#sandbox #java_database_tools_starter
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26❤4
Всем привет! 👋
Последнее время пропал с радаров🫠
Довольно много времени уходило на подготовку статьи и постоянно откладывал на потом, чтобы написать в желаемом качестве, и вот уже прошел не один месяц😵💫
Помимо этого, стал больше изучать алгоритмы, но чтобы писать по ним статьи, еще нужно разобраться👨💻
Также недавно я проходил Mock Coding Interview у автора канала FAANG Master✈️ . Было полезно. Искренне рекомендую вам этот канал, если вам интересна эта тема.
И напоследок:
Как-то в первом сообщении на канале я упоминал, что интересно было бы и самому проводить Mock-интервью [бесплатно] на Java разработчика [Junior, Middle, Senior].
Хотел бы узнать, насколько это интересно вам, - поэтому жду ваших реакций:
👍 — если интересно пройти Mock-интервью
Последнее время пропал с радаров
Довольно много времени уходило на подготовку статьи и постоянно откладывал на потом, чтобы написать в желаемом качестве, и вот уже прошел не один месяц
Помимо этого, стал больше изучать алгоритмы, но чтобы писать по ним статьи, еще нужно разобраться
Также недавно я проходил Mock Coding Interview у автора канала FAANG Master
И напоследок:
Как-то в первом сообщении на канале я упоминал, что интересно было бы и самому проводить Mock-интервью [бесплатно] на Java разработчика [Junior, Middle, Senior].
Хотел бы узнать, насколько это интересно вам, - поэтому жду ваших реакций:
👍 — если интересно пройти Mock-интервью
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71
Всем привет! 👋
Наконец-то получилось подготовиться и освободить время под Mock interview📞
Планирую примерно такой формат:
0⃣ Делаю пост о свободном времени с ссылкой на Google Meet, где можно забронировать встречу, выбрав подходящее время.
1⃣ Встречаемся в назначенное время в Google Meet. [Камера по желанию]
2⃣ Строим план собеседования и разговариваем про опыт. [Собеседование на русском, в будущем можно будет на английском]
3⃣ Вопросы будут про — Java, Spring, работу с БД, очереди. [И некоторые другие общие вопросы, зависит от уровня собеседуемого]
4⃣ Длительность собеседования около часа, но тут как пойдет.
5⃣ В конце делимся отзывами о том как прошло интервью.
6⃣ Mock interview постараюсь построить так, чтобы было интересно специалистам уровня junior/middle/senior.
7⃣ Запись видео индивидуально по желанию, выкладывать на канал не планирую
И уже сегодня хочу устроить тестирование этого формата, есть 2 места, если есть желающие, буду рад👨💻
Забронировать время на сегодня можно по ссылке — mock
Если есть вопросы/пожелания, буду ждать в комментариях🤔
Наконец-то получилось подготовиться и освободить время под Mock interview
Планирую примерно такой формат:
И уже сегодня хочу устроить тестирование этого формата, есть 2 места, если есть желающие, буду рад
Забронировать время на сегодня можно по ссылке — mock
Если есть вопросы/пожелания, буду ждать в комментариях
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13❤3👍3
Всем привет! 💻
Добавил 2 места на Mock interview:
1⃣ В субботу на 18:00 (GMT+3)
2⃣ В воскресенье на 15:00 (GMT+3)
Записаться можно по ссылке — mock✅ [edited: все забронировано]
Напоминаю формат:
1⃣ Встречаемся в назначенное время в Google Meet. [Камера по желанию]
2⃣ Строим план собеседования и разговариваем про опыт. [Собеседование на русском, в будущем можно будет на английском]
3⃣ Вопросы будут про — Java, Spring, работу с БД, микросервисы, очереди и т.д. что является сейчас актуальным
4⃣ Подойдет уровням Junior/Middle/Senior
5⃣ Сразу отвечать на вопросы не будем, а будем идти дальше. Весь разбор и фидбек в конце интервью, где мы обменяемся отзывами
Кое что изменил:
1⃣ Длительность собеседования будет 1.5 часа, в прошлый раз часа не хватило
2⃣ Сделаю митинг публичным и опубликую на канале ссылку, чтобы каждый мог в качестве зрителя зайти и посмотреть. Но запись самого собеседования все еще будет по желанию.
3⃣ Желательно иметь установленную IDE [Я надеюсь успеть подготовить некоторые практические задачи]
Если есть вопросы, буду ждать в комментариях👨💻
Добавил 2 места на Mock interview:
Записаться можно по ссылке — mock
Напоминаю формат:
Кое что изменил:
Если есть вопросы, буду ждать в комментариях
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10
[edited: завершено]
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8
