В новом переводе от команды Spring АйО вы узнаете, как минимизировать риски и обеспечить безопасность Docker-контейнеров с помощью CIS Benchmark рекомендаций и автоматизированных инструментов вроде Docker Bench for Security.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍5❤4👎1🤔1🤩1
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
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁42👍6🔥4
Со временем в любом приложении могут появиться дублирующиеся записи. Иногда их удаление реализуют на уровне приложения, хотя это можно сделать с помощью одного SQL-запроса.
Удалить дубликаты вручную не так просто, как может показаться. Обычно для этого используется команда
GROUP BY
с функциями MIN(id)
или MAX(id)
, чтобы оставить одну строку.
DELETE FROM contacts
WHERE id NOT IN (
SELECT MIN(id)
FROM contacts
GROUP BY firstname, lastname, email
);
Однако такой метод не всегда подходит, если есть дополнительные требования:
* Нужно сохранить не все дубликаты, а лишь часть, например, последние пять.
* Иногда важно не просто удалить первые или последние строки — дополнительные поля могут задавать приоритет, например, мы не хотим удалять пользователя, подтвердившего
email
, ради того, который этого не сделал.Чтобы учесть все требования, можно воспользоваться оконными функциями:
1. Строки разбиваются на группы по дублирующимся полям, создавая отдельные группы для каждого уникального набора значений.
2. Каждая группа сортируется по важным полям, например, по дате создания.
3. Для каждой строки в группе с помощью функции
ROW_NUMBER
назначается порядковый номер.4. Можно удалить любые строки с номером, превышающим необходимый, например, если нужно оставить только пять последних записей.
Тогда, запрос позволяющий сохранить не все дубликаты, а лишь часть, например, последние пять, будет выглядеть следующим образом:
WITH duplicates AS (
SELECT id, ROW_NUMBER() OVER(
PARTITION BY firstname, lastname, email
ORDER BY age DESC
) AS rownum
FROM contacts
)
DELETE FROM contacts
USING duplicates
WHERE contacts.id = duplicates.id AND duplicates.rownum > 5;
А запрос, для удаления дубликатов с учетом факта подтверждения
email
следующим образом:
WITH duplicates AS (
SELECT
id,
ROW_NUMBER() OVER(
PARTITION BY email
ORDER BY email_confirmed DESC
) AS rownum
FROM contacts
)
DELETE FROM contacts
USING duplicates
WHERE contacts.id = duplicates.id AND duplicates.rownum > 1;
#DatabaseTip #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
👍37❤4🔥4🤩1
Компания JetBrains начала блокировать лицензии пользователей, находящихся в России. Несмотря на то, что ранее была возможность обходить ограничения через изменение страны проживания и использование иностранных банковских карт, теперь лицензии могут быть заблокированы без предупреждения.
Вот что отвечает тех. поддержка JetBrains пользователям, чьи лицензии были заблокированы:
Наша команда по соблюдению правил выявила использование вашей лицензии на территории Российской Федерации, что нарушает условия нашей лицензии и действующие экспортные ограничения. К сожалению, я вынужден сообщить вам, что ваша лицензия была приостановлена в связи с нарушением лицензионного соглашения.
Официальная позиция нашей компании следующая: в соответствии с правилами ЕС, определённые продукты JetBrains, включая наши IDE, Code With Me, Upsource, TeamCity и Space для локального использования, относятся к категории продуктов массового рынка с функциями шифрования (X.D.III.201). Как следствие, экспорт таких продуктов, включая их передачу в Российскую Федерацию, запрещён. Кроме того, предоставление решений для управления проектами (таких как YouTrack), услуг по IT-консалтингу и технической поддержке также запрещено.
Напоминаем, что JetBrains приостановила продажи в Российской Федерации и Беларуси в 2022 году. Вдобавок к этому, в соответствии с вышеуказанными правилами, JetBrains не может предоставлять прямую или косвенную поддержку ни одной организации или государственному органу в Российской Федерации, а также запрещена передача наших продуктов, использующих массовое шифрование или инструменты управления проектами, для использования в Российской Федерации без соответствующего разрешения на исключение из этих правил.
🔗 Источник: https://habr.com/ru/news/852254/
#breaking_news #ide #jetbrains #sber
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯61👎41👍7❤5⚡2🔥2
На российском рынке сложилась сложная ситуация с IDE для Java-разработчиков. Новости, связанные с ограничением скачивания IntelliJ IDEA Ultimate, недоступностью JetBrains маркетплейса и блокировкой лицензий, которые использовались на территории РФ порождают огромное количество вопросов, на которые не у всех есть ответы.
Команда Spring АйО подготовила цикл статей, в которых постарается ответить на все вопросы, связанные с уходом IntelliJ IDEA из России.
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍36🔥9❤4👎4⚡3🤔1
С выходом Java 23 произошли важные изменения в формате написания комментариев — теперь они могут быть написаны с использованием
Markdown
. Ранее разработчики использовали HTML
и JavaDoc
-теги для оформления таких комментариев, что могло создавать сложности, особенно для тех, кто не знаком с HTML
. Теперь, благодаря поддержке Markdown
, комментарии станет писать проще и удобнее.Зачем это нужно?
HTML
с течением времени стал менее популярен для ручного написания. Сегодня чаще используют языки разметки, ориентированные на удобство разработчиков. Использование HTML
для JavaDoc
создавало трудности, так как он тяжеловесен и сложен для быстрого написания, особенно для новых разработчиков.Преимущества использования Markdown
Markdown
стал популярным благодаря своей простоте и удобочитаемости. Он идеально подходит для написания JavaDoc
, которая обычно состоит из текстовых блоков, списков, ссылок и выделенного текста. Вместо сложных HTML
-тегов можно использовать гораздо более лаконичные конструкции Markdown
.Вот так выглядит комментарий к методу
hashCode
с использованием HTML
и JavaDoc
-тегов:
/**
* Возвращает хэш-код для объекта.
* <p>
* Общий контракт метода {@code hashCode}:
* <ul>
* <li>Если метод вызывается несколько раз на одном объекте в ходе выполнения программы,
* он должен возвращать одно и то же значение, если данные объекта не изменялись.
* <li>Если два объекта равны, вызов метода {@code hashCode} должен вернуть одинаковое значение.
* <li>Если объекты не равны, метод может возвращать одинаковые хэш-коды, но этого следует избегать.
* </ul>
* @return хэш-код для объекта.
*/
Этот же комментарий в
Markdown
:
/// Возвращает хэш-код для объекта.
///
/// Общий контракт метода `hashCode`:
///
/// - Если метод вызывается несколько раз на одном объекте в ходе выполнения программы,
/// он должен возвращать одно и то же значение, если данные объекта не изменялись.
/// - Если два объекта равны, вызов метода `hashCode` должен вернуть одинаковое значение.
/// - Если объекты не равны, метод может возвращать одинаковые хэш-коды, но этого следует избегать.
///
/// @return хэш-код для объекта.
Для использования
Markdown
введён новый формат комментариев: строки начинаются с трёх слэшей (`///`), вместо традиционного синтаксиса /** ... */. Основные различия:
- Пробел между абзацами обозначается пустой строкой, как и в
Markdown
.- Списки создаются с помощью маркеров - вместо
HTML
-тегов <ul> и <li>.- Подчёркивание (`_`) используется для выделения текста, вместо
HTML
-тегов <em>.- Теги вроде {@code} заменяются обратными апострофами (\`...\`).
В то же время, важные теги, такие как @param и @return, сохраняются и могут использоваться вместе с
Markdown
-разметкой.🔗 С полным описанием JEP можно ознакомиться по ссылке: https://openjdk.org/jeps/467
#Java #JEP
Please open Telegram to view this post
VIEW IN TELEGRAM
👍36🤔15❤5🔥5👌1
🛠️ Функциональные HTTP-эндпоинты с Spring MVC/WebFlux и Kotlin
Функциональные подходы к разработке в Spring становятся все более популярными благодаря своей гибкости и лаконичности.
В новой статье от эксперта сообщества Spring АйО, Михаила Поливахи, рассматривается, как можно эффективно определять HTTP-эндпоинты с использованием Spring MVC/WebFlux, применяя функциональный стиль программирования на языке Kotlin.
📚 Читать на Хабре: https://habr.com/ru/companies/spring_aio/articles/853126/
Функциональные подходы к разработке в Spring становятся все более популярными благодаря своей гибкости и лаконичности.
В новой статье от эксперта сообщества Spring АйО, Михаила Поливахи, рассматривается, как можно эффективно определять HTTP-эндпоинты с использованием Spring MVC/WebFlux, применяя функциональный стиль программирования на языке Kotlin.
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍19❤5🔥5
В первом выпуске подкаста Spring АйО в студии собрались 4 эксперта сообщества, чтобы попытаться раз и навсегда ответить на вопрос: "Чем же для нас стал Spring: эволюцией или революцией?"
💬 Аудио версию подкаста можно найти в комментариях
P.S. Поддержите нас лайками и репостами, если понравится формат и если вы бы хотели чаще слышать обсуждения экспертов сообщества на различные темы
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍33🔥15❤8🤩2
Anonymous Poll
84%
Spring Web
22%
Spring Reactive Web (WebFlux)
5%
Spring for GraphQL
6%
Spring Web Services (SOAP)
6%
Spring Cloud Function
13%
gRPC
3%
Jersey
4%
Свой вариант ответа. Напишу в комментариях
🔥14🤔9👍7❤2
Для тех, кто был слишком занят на неделе или просто пропустил некоторые посты, публикуем дайджест!
– Безопасный Docker в продакшене – познакомились со способами обеспечения безопасности Docker-контейнеров
– Удаление дублирующихся строк – разобрались с удалением дублирующихся строк одним SQL-запросом
– Компания JetBrains начала блокировать оплаченные лицензии пользователей, находящихся на территории РФ – сообщили об ограничениях со стороны продуктов JetBrains в отношении пользователей из РФ, а также о возможных способах решения проблем, связанных с этими ограничениями
– Как жить без IntelliJ IDEA? Часть №1. Собери сам! – выпустили первую статью из цикла "Как жить без IntelliJ IDEA", в которой рассмотрели альтернативы полюбившейся многим IDE
– JEP 467: Markdown в JavaDoc – рассказали про изменения формата написания комментариев JavaDoc в 23 версии Java
– Функциональные HTTP-эндпоинты с Spring MVC/WebFlux и Kotlin – познакомились с эффективным способом определения HTTP-эндпоинтов, используя функциональный стиль программирования
– Spring – эволюция или революция!? – выпустили первый подкаст с участием экспертов сообщества Spring АйО
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥9❤4
В первой статье из цикла "Как жить без IntelliJ IDEA" мы рассмотрели возможные альтернативы привычной многим IDE.
Во второй статье из цикла команда Spring АйО выяснила, какие есть альтернативы Ultimate в части поддержки Spring и насколько хорошо они справляются со своей задачей.
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤21👍10🔥4⚡2👎2
При юнит-тестировании часто требуется проверить методы, которые используют цепочки вызовов, например, в WebClient из Spring WebFlux.
⚠️ Если задача позволяет, лучше воспользоваться MockWebServer или WireMock для гибкого тестирования HTTP-клиентов. Здесь WebClient выбран лишь из-за своей наглядности и популярности.
Представим клиент, запрашивающий случайную цитату у удалённого сервиса:
public class InspirationalQuotesClient {
private final WebClient webClient;
public InspirationalQuotesClient(WebClient webClient) {
this.webClient = webClient;
}
public String fetchRandomQuote() {
try {
return this.webClient
.get()
.uri("/api/quotes")
.retrieve()
.bodyToMono(String.class)
.block();
} catch (WebClientException e) {
return "Every time a mock returns, a mock a fairy dies.";
}
}
}
Для тестирования такого клиента стандартным способом нужно замокировать каждый вызов в цепочке, чтобы избежать
NullPointerException
. Это может сделать тест слишком громоздким:
@ExtendWith(MockitoExtension.class)
class InspirationalQuotesClientTest {
@Mock private WebClient webClient;
@InjectMocks private InspirationalQuotesClient cut;
@Test
void shouldReturnInMockingHell() {
WebClient.RequestHeadersUriSpec requestHeadersUriSpec = Mockito.mock(WebClient.RequestHeadersUriSpec.class);
WebClient.ResponseSpec responseSpec = Mockito.mock(WebClient.ResponseSpec.class);
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri("/api/quotes")).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just("We've escaped hell"));
String result = cut.fetchRandomQuote();
assertEquals("We've escaped hell", result);
}
}
Решение? Deep Stubs в Mockito. С ними можно упростить тест, описав всю цепочку вызовов сразу в конструкции
when
. Это значительно уменьшит количество кода:
@ExtendWith(MockitoExtension.class)
class DeepStubClientTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private WebClient webClient;
@InjectMocks private InspirationalQuotesClient cut;
@Test
void shouldReturnQuoteFromRemoteSystem() {
Mockito.when(webClient.get().uri("/api/quotes").retrieve().bodyToMono(String.class))
.thenReturn(Mono.just("Less setup hell - but not better"));
String result = cut.fetchRandomQuote();
assertEquals("Less setup hell - but not better", result);
}
}
Используя параметр
answer = Answers.RETURNS_DEEP_STUBS
, мы возвращаем заглушку для каждого метода в цепочке. Но помните, что этот подход увеличивает зависимость теста от конкретной структуры вызовов, и любые изменения в цепочке потребуют изменений в тесте.P.S. А как вы мокируете вызовы внешних API?
Ставьте 🔥 если считаете функциональность полезной.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥41👍9❤7⚡4👎4🤯2
Команда Spring АйО перевела статью об исследовании Uplevel, которое показало, что использование GitHub Copilot не улучшает производительность разработчиков, а наоборот — увеличивает количество ошибок в коде.
Разработчики стали тратить больше времени на проверку ИИ-сгенерированного кода, что снижает ожидаемую экономию времени. Хотя компании активно внедряют ИИ-инструменты, их реальная польза для повышения продуктивности остается под вопросом.
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍23🔥7⚡5❤3
🧩 Исключение строк из уникальных индексов
Представьте, что вам нужно поддерживать уникальность данных, например, адресов электронной почты в таблице базы данных. Но что делать, если в таблице есть строки, помеченные как удаленные, например, с помощью дополнительного поля
Partial индекс позволяет задать условие (например,
⚠️ Советуем сделать бэкап своей БД перед выполнением запросов во избежании потери данных
Реализация
В PostgreSQL добавление уникального индекса для активных пользователей выглядит так:
В этом случае строки, у которых
Для MySQL требуется обходной путь, так как partial индексы в нем не поддерживаются. С использованием конструкции
Здесь
Как это работает?
Есть некое свойство базы данных, что значения
Преимущества частичных индексов
Кроме того, partial индексы сокращают объем данных, включаемых в индекс, тем самым экономя место и ускоряя операции поиска. PostgreSQL предлагает удобный и простой способ реализации частичных индексов, в то время как MySQL требует определенных обходных решений.
Представьте, что вам нужно поддерживать уникальность данных, например, адресов электронной почты в таблице базы данных. Но что делать, если в таблице есть строки, помеченные как удаленные, например, с помощью дополнительного поля
deleted_at
? При этом важно учитывать, что удаленные данные тоже находятся в таблице, поэтому в поле с почтой будут дубли, сделать уникальный индекс не получится. Здесь на помощь приходят partial индексы.Partial индекс позволяет задать условие (например,
WHERE deleted_at IS NULL
), чтобы включать только нужные строки и игнорировать удаленные. Эта функция доступна в PostgreSQL, где можно исключать строки с soft delete, сохраняя требуемую уникальность и оптимизируя размер индекса.Реализация
В PostgreSQL добавление уникального индекса для активных пользователей выглядит так:
CREATE UNIQUE INDEX users_email_uniq ON users (
) WHERE deleted_at IS NULL;
В этом случае строки, у которых
deleted_at
не задан, включаются в индекс, а остальные игнорируются, что делает индекс более компактным и эффективным.Для MySQL требуется обходной путь, так как partial индексы в нем не поддерживаются. С использованием конструкции
IF(deleted_at, NULL, 1)
можно эмулировать аналогичное поведение. Пример индекса:
CREATE UNIQUE INDEX users_email_uniq ON users (
email,
(IF(deleted_at, NULL, 1))
);
Здесь
NULL
используется чтобы исключить удаленные строки из индекса: строки, помеченные как удаленные, получают значение NULL
и не конфликтуют с другими значениями.Как это работает?
Есть некое свойство базы данных, что значения
NULL
не рекомендуется сравнивать ни с чем, используя ANSI SQL стандартные операторы (=, !=, <> и т.д.), т.к. сравнение приведёт к unknown
. Получится так, что два значения (example@example.com, null)
в индексе могут спокойно существовать, в то время как два значения (example@example.com, 1)
будут конфликтовать. Это свойство позволяет обойти ограничение MySQL и реализовать функциональность partial индекса. Например, строка с адресом foo@example.com
, если пользователь помечен как удаленный, получит значение индекса (foo@example.com, NULL)
и не создаст конфликта, даже если аналогичная строка существует. Такая стратегия помогает соблюсти уникальность данных, сохраняя логическую целостность таблицы и избегая лишних конфликтов в MySQL.Преимущества частичных индексов
Кроме того, partial индексы сокращают объем данных, включаемых в индекс, тем самым экономя место и ускоряя операции поиска. PostgreSQL предлагает удобный и простой способ реализации частичных индексов, в то время как MySQL требует определенных обходных решений.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍35🔥13❤6🤩1
🧠 AI-ассистент со Spring AI (Часть 2)
Не так давно мы публиковали первую часть статьи по написанию AI-ассистента со Spring AI. В продолжении статьи автор углубляется в возможности генерации с поддержкой поиска (RAG), чтобы LLM могла учесть некоторую контекстуальную информацию данных, превоначально невходившую в ее обучающую выборку.
В новом переводе от команды Spring АйО рассматривается польза Spring AI и векторной БД, благодаря которым система не просто сопоставляет ключевые слова, но и понимает смысловые запросы пользователей, делая взаимодействие с приложением еще более естественным.
📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/855398/
Не так давно мы публиковали первую часть статьи по написанию AI-ассистента со Spring AI. В продолжении статьи автор углубляется в возможности генерации с поддержкой поиска (RAG), чтобы LLM могла учесть некоторую контекстуальную информацию данных, превоначально невходившую в ее обучающую выборку.
В новом переводе от команды Spring АйО рассматривается польза Spring AI и векторной БД, благодаря которым система не просто сопоставляет ключевые слова, но и понимает смысловые запросы пользователей, делая взаимодействие с приложением еще более естественным.
📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/855398/
👍11🔥8❤4