Spring АйО
Русскоязычное сообщество разработчиков на Spring Boot. Habr: https://habr.com/ru/companies/spring_aio Канал для общения: @spring_aio_chat #spring_boot #spring #java #kotlin #jvm #docker
Больше1 753
Подписчики
+6324 часа
+3297 дней
+1 04230 дней
- Подписчики
- Просмотры постов
- ER - коэффициент вовлеченности
Загрузка данных...
Прирост подписчиков
Загрузка данных...
Фото недоступноПоказать в Telegram
📝 Переписывая историю: от инструментов версионирования БД к практике
Пожалуй, почти каждый Spring разработчик сталкивается в своей практике с версионированием баз данных. На эту тему есть отличный доклад на Joker 2023 от Александра Шустанова, в котором спикер сравнивает 2 самых популярных инструмента для миграций БД: Flyway и Liquibase. Редакция Spring АйО приводит транскрипт доклада, для тех, у кого нет 45 минут для просмотра видео.
В статье вас ожидает обзор ключевых особенностей Liquibase и Flyway, а также сравнение их возможностей. Расскажем, когда нужно создавать миграции, как облегчить этот процесс и уменьшить количество ошибок. Осветим некоторые малоизвестные возможности этих инструментов и развеем мифы о других.
📚 Подробнее читайте на Хабре
👍 13🔥 7❤ 4
👨💻 Spring Boot Tips: Кастомные реализации репозиториев
Spring Data упрощает создание запросов, но стандартные методы не всегда подходят под конкретные задачи. В таких случаях мы можем создать собственные реализации методов репозиториев. Например, если мы хотим, чтобы запрос формировался динамически на основе фильтра и возвращал DTO с меньшим количеством полей, нам понадобится создать fragment interface и кастомный метод с собственной реализацией.
//Кастомный интерфейс
public interface CustomizedUserRepository {
List<UserDto> findAllUsers(UserFilter filter);
}
//Реализация нашего интерфейса, которая будет использоваться Spring'ом
public class CustomizedUserRepositoryImpl implements CustomizedUserRepository {
private final EntityManager em;
public CustomizedUserRepositoryImpl(JpaContext jpaContext) {
em = jpaContext.getEntityManagerByManagedType(User.class);
}
//Реализация нашего метода
@Override
public List<UserDto> findAllUsers(UserFilter filter) {
var cb = em.getCriteriaBuilder();
var query = cb.createQuery(UserDto.class);
var root = query.from(User.class);
var emailPath = root.<String>get(User_.EMAIL);
var usernamePath = root.<String>get(User_.USERNAME);
query.multiselect(root.get(User_.ID), emailPath, usernamePath);
var predicates = new ArrayList<Predicate>();
var email = filter.email();
if (StringUtils.hasLength(email)) {
predicates.add(cb.like(cb.lower(emailPath), "%" + email.toLowerCase() + "%"));
}
var username = filter.username();
if (StringUtils.hasLength(username)) {
predicates.add(cb.like(cb.lower(usernamePath), "%" + username.toLowerCase() + "%"));
}
query.where(predicates.toArray(new Predicate[]{}));
return em.createQuery(query).getResultList();
}
}
//Использование кастомного интерфейса
interface UserRepository extends CrudRepository<User, Long>, CustomizedUserRepository {}
Теперь при инжекции UserRepository
, кастомный метод будет доступен для вызова:
List<UserDto> users = userRepository.findAllUsers(new UserFilter("Maksim", null));
Важные замечания
1. CustomizedUserRepositoryImpl
— полноценный Spring-бин, поддерживающий инжекцию других бинов и специфическую функциональность (AOT, Lifecycle Callbacks и т.д.).
2. Инжекция UserRepository
может привести к циклической зависимости. Чтобы избежать этого, его можно получить через ApplicationContext.getBean()
.
3. Spring пытается автоматически обнаружить пользовательские fragment интерфейсы, если классы следуют соглашению об именовании с постфиксом Impl
. Модифицировать значение по умолчанию можно через атрибут аннотации @EnableJpaRepositories
:
@EnableJpaRepositories(repositoryImplementationPostfix = "MyPostfix")
4. Репозитории могут включать несколько пользовательских реализаций, которые имеют более высокий приоритет, чем базовая реализация, что позволяет переопределять базовые методы. Например, создадим кастомный интерфейс и переопределим метод save
:
public interface CustomizedSave<T> {
<S extends T> S save(S entity);
}
class CustomizedSaveImpl<T> implements CustomizedSave<T> {
@Override
public <S extends T> S save(S entity) {
// наша кастомная реализация
}
}
Теперь, если мы объявим следующий репозиторий:
interface UserRepository extends CrudRepository<User, Long>, CustomizedSave<User> {}
то при вызове метода userRepository.save(user)
будет использован метод из нашей реализации CustomizedSaveImpl
.
5. В примерах выше мы рассматривали Spring Data JPA, но эта концепция поддерживается для всех модулей Spring Data (MongoDB, Redis, JDBC и т.д.).
Подробнее про реализацию кастомных репозиториев читайте в документации.
#SpringTips #SpringBoot #CustomRepository👍 21🔥 8👌 3
Фото недоступноПоказать в Telegram
🔍 Как избежать утечек соединений в Spring Boot приложении?
В новом переводе от команды Spring АйО вы узнаете, как аннотация
@Transactional
помогла решить проблему с утечкой соединений и обеспечила стабильность системы.
Недавно мы обнаружили критическую проблему внутри слоя репозиториев в нашем микросервисном Spring приложении: неправильная обработка исключения приводила к неожиданным сбоям и нарушению работы сервиса во время тестирования производительности.📚Подробнее читайте на Хабр: https://habr.com/ru/article/edit/827642/
🔥 14👍 7❤ 2
Repost from Java Developer
Фото недоступноПоказать в Telegram
👩💻 Liquibase + Spring Boot: настройка и написание миграций баз данных
Благодаря этой статье вы узнаете, как подключить и настроить Liquibase в Spring Boot приложении, сгенерировать скрипты инициализации и миграции схемы БД, а также дополнить уже существующие changelog файлы новыми скриптами миграции.
Ссылка на статью — КЛИК
➡️ Java Developer | #статья #spring
🔥 12👍 6👌 4
🛡 Spring Boot Tips: Service Layer Validation
Валидация данных – ключевой аспект любого приложения. В Spring она часто используется в параметрах методов
@RestController
, например:
@RestController
@RequestMapping("/api/products")
public class ProductController {
@GetMapping("/search")
public ResponseEntity<List<Product>> searchProducts(@RequestParam @NotNull @Size(min = 3, max = 50) String name,
@RequestParam @NotNull @Min(0) @Max(10000) Double price) {
// Логика поиска продуктов
List<Product> products = productService.search(name, price);
return new ResponseEntity<>(products, HttpStatus.OK);
}
}
Валидация в сервисном слое
Валидация помогает гарантировать, что данные, поступающие в приложение, соответствуют требованиям. Для валидации в сервисном слое нужно добавить аннотацию @Validated
над сервисом:
@Service
@Validated
public class EmailService {
public void send(@Email String email,
@Length(max = 10) String subject,
@NotBlank String body) {
// бизнес-логика
}
}
Теперь метод send вызовет ошибку, если данные не проходят валидацию:
emailService.send(
"i am not email",
"I am too loooooooooong",
""
);
jakarta.validation.ConstraintViolationException: send.body: must not be blank, send.email: must be a well-formed email address, send.subject: length must be between 0 and 10 ...Валидация DTO в методах сервиса Чтобы не дублировать поля в разных методах, разработчики часто используют DTO. Аннотации валидации применимы и здесь:
public record EmailRequest(
@Email String email,
@Length(max = 10) String subject,
@NotBlank String body
) {
}
Но в этом случае помимо @Validated
над классом, нужно также не забыть добавить @Valid
перед типом параметра в методе:
@Service
@Validated
public class EmailService {
public void sendBatch(
@Valid List<EmailRequest> requests
) {
// do work
}
}
Следующий код вызовет ошибку:
emailService.sendBatch(
List.of(
new EmailRequest("not email", "test", "Hello"),
new EmailRequest("[email protected]", "I am too loooooooooong", "")
)
);
jakarta.validation.ConstraintViolationException: sendBatch.requests[1].subject: length must be between 0 and 10, sendBatch.requests[1].body: must not be blank, sendBatch.requests[0].email: must be a well-formed email addressВалидация элементов коллекций Кстати, точно также можно валидировать и элементы коллекций, а также ключи и значения в Map:
@Service
@Validated
public class EmailService {
public void search(
Map<@NotBlank String, @NotBlank String> searchParams
) {
// do work
}
}
Следующий код вызовет ошибку:
searchService.search(Map.of("", ""));
jakarta.validation.ConstraintViolationException: search.searchParams<K>[].<map key>: must not be blank, search.searchParams[].<map value>: must not be blank#SpringBoot #SpringTips #Validation
👍 41🔥 12❤ 2👌 1
🗓 Еженедельный дайджест №3
Для тех, кто был слишком занят на неделе или просто пропустил некоторые посты, публикуем дайджест!
– Как управлять запуском различных сервисов в Docker Compose? Узнали, что профили есть не только в Spring!
– Почему String Templates не будет в Java 23? Получили хоть и не всеобъемлющий, но ответ на вопрос, почему String Templates были удалены из Java после нескольких итераций preview.
– GigaIDE — новая IDE от Сбера. Что тут говорить. Самая громкая новость последних дней. 200+ комментариев под постом на Хабре не дадут соврать.
– Тестирование Spring Boot приложений. Лучшие практики. Судя по комментариям, некоторые из перечисленных практик могли показаться очевидными, но услышать их хотя бы раз точно стоит.
– Новый компилятор K2 в Kotlin. Часть 2. Продолжили изучать новые возможности K2 в Kotlin вместе с Михаилом Поливахой.
– Markdown в IntelliJ IDEA как отдельный вид искусства. Рисуем диаграммы и вызываем bash команды. Рассказали, как можно использовать Markdown файлы в IntelliJ IDEA по максимуму.
– Знакомьтесь, James Gosling: Отец Java. А завершили неделю с одной стороны замечательной, с другой стороны немного грустной новостью про уход на пенсию Джеймса Гослинга.
😌 Подписывайтесь на канал: @spring_aio
💬 Вступайте в чат: @spring_aio_chat
👍 22🔥 6❤ 5
Фото недоступноПоказать в Telegram
🖥 Знакомьтесь, James Gosling: Отец Java
Джеймс Гослинг — канадский программист и инженер, создавший Java в начале 90-х годов. Его цель была ясна: создать язык, позволяющий писать программы, независимые от платформы. Так появился лозунг "Write Once, Run Anywhere", который революционизировал разработку ПО, позволяя Java-приложениям работать на любых устройствах с поддержкой JVM.
Недавно Джеймс сообщил, что уходит на заслуженный отдых:
Я наконец-то вышел на пенсию. После долгих лет работы программистом, пришло время просто наслаждаться жизнью. Последние 7 лет в Amazon были отличными, несмотря на COVID-19 и производственные проблемы. У меня есть длинный список сайд-проектов, которые нужно завершить. Будет весело.Мы, как Spring-разработчики, благодарим Джеймса. Без его новаторских идей и разработки Java, возможно, у нас не было бы нашего любимого фреймворка 💚
❤ 56👍 12🔥 7
Фото недоступноПоказать в Telegram
Markdown в IntelliJ IDEA как отдельный вид искусства. Рисуем диаграммы и вызываем bash команды
Spring разработчики часто пишут документацию и README/HELP файлы к своим приложениям. Часто это делается в Markdown файлах. Markdown плагин в IntelliJ IDEA распознает файлы, предоставляет специальный редактор с подсветкой, автокомплитом и форматированием, а также предлагает визуальное отображение в панели предварительного просмотра в реальном времени. Кроме стандартной функциональности в IntelliJ IDEA есть пару уникальных фич, которые редакция Spring АйО хотел выделить особенно.
📚 Интересно? Читайте продолжение на Хабре
👍 21🔥 3😁 2❤ 1
Фото недоступноПоказать в Telegram
🆕 Новый компилятор K2 в Kotlin. Часть 2
Встречайте вторую часть статьи "Новый компилятор K2 в Kotlin" от эксперта сообщества Spring АйО – Михаила Поливахи!
В первой части Михаил рассказал про компилятор К2 в общем, а во второй части сфокусировался только на процедуре миграции.
📚 Подробней читайте на Хабре
P.S. Будем благодарны за лайки на статье на Habr 💚
👍 12❤ 3🔥 3
🐞 Тестирование Spring Boot приложений. Лучшие практики.
Автоматизированное тестирование Spring-приложений стало неотъемлимой частью разработки. Единственный выбор, с котором сегодня сталкиваются разработчики: сначала писать тесты или функциональность?
А в ситуации, когда тесты становятся обязательными, возникает вопрос: насколько они хороши?
Филип Рикс собрал лучшие практики тестирования в одной статье, объясняя их важность и рассказывая почему стоит им следовать (en): https://rieckpil.de/spring-boot-testing-best-practices/
😌 Подписывайтесь на канал: @spring_aio
💬 Вступайте в чат: @spring_aio_chat
Spring Boot Testing Best Practices - rieckpil
Learn about the top five Spring Boot testing best practices to build and maintain Spring Boot applications more confidently.
👍 11❤ 7🔥 3
Выберите другой тариф
Ваш текущий тарифный план позволяет посмотреть аналитику только 5 каналов. Чтобы получить больше, выберите другой план.