🎉 Встречайте нашу дебютную статью на Habr!
👩💻 Блеск и нищета нового Scrolling API в Spring Data
В статье мы разобрали новое Scrolling API, которое предназначено для эффективной пагинации. В частности, Scrolling API приносит KeySet пагинацию в Spring Data, которая в теории может быть сильно быстрее стандратной и всем известной offset пагинации.
Однако, в процессе исследования выяснилось, что с PostgreSQL новое API работает не совсем так, как ожидается. А ведь это одна из самых популярных СУБД в мире!
Заинтриговали? Переходите по ссылке, оставляйте комментарии, и, конечно, ждем ваших лайков)
🔗 https://habr.com/ru/companies/spring_aio/articles/819193/
#SpringBoot #SpringData
Подписывайтесь:
😌 @spring_aio
В статье мы разобрали новое Scrolling API, которое предназначено для эффективной пагинации. В частности, Scrolling API приносит KeySet пагинацию в Spring Data, которая в теории может быть сильно быстрее стандратной и всем известной offset пагинации.
Однако, в процессе исследования выяснилось, что с PostgreSQL новое API работает не совсем так, как ожидается. А ведь это одна из самых популярных СУБД в мире!
Заинтриговали? Переходите по ссылке, оставляйте комментарии, и, конечно, ждем ваших лайков)
🔗 https://habr.com/ru/companies/spring_aio/articles/819193/
#SpringBoot #SpringData
Подписывайтесь:
Please open Telegram to view this post
VIEW IN TELEGRAM
🌟 Статическая и динамическая конфигурация в Spring Boot: что выбрать?
В мире облачных сервисов правильная настройка конфигурации играет ключевую роль. В этой статье рассматриваются два подхода: статическая и динамическая конфигурация.
🔧 Статическая конфигурация удобна предсказуемостью и простотой развертывания. Пример на Spring Boot:
🔄 Динамическая конфигурация обеспечивает гибкость и адаптивность. Например, для изменения конфигураций во время выполнения приложения можно использовать Spring Cloud:
Spring Cloud предоставляет возможность создания config сервера, который может подгружать новые конфигурации из Git. Ознакомьтесь с полной статьей для более детального погружения и примеров кода!
📚 Читать далее
#SpringBoot #SpringCloud
В мире облачных сервисов правильная настройка конфигурации играет ключевую роль. В этой статье рассматриваются два подхода: статическая и динамическая конфигурация.
🔧 Статическая конфигурация удобна предсказуемостью и простотой развертывания. Пример на Spring Boot:
@Value("${myapp.staticValue}")
private String staticValue;
public void printStaticValue() {
System.out.println(staticValue);
}
🔄 Динамическая конфигурация обеспечивает гибкость и адаптивность. Например, для изменения конфигураций во время выполнения приложения можно использовать Spring Cloud:
@RefreshScope
@RestController
public class MessageRestController {
@Value("${message:Hello default}")
private String message;
@GetMapping("/message")
public String getMessage() {
return this.message;
}
}
Spring Cloud предоставляет возможность создания config сервера, который может подгружать новые конфигурации из Git. Ознакомьтесь с полной статьей для более детального погружения и примеров кода!
📚 Читать далее
#SpringBoot #SpringCloud
EqualsVerifier отмечает 15-летие 🥳
Переопределение методов equals() и hashCode() – непростая задача. Они должны соответствовать не только требованиям Java, но и используемому стеку технологий (например, JPA).
Библиотека EqualsVerifier помогает разработчикам проверить корректность переопределенных методов уже 15 лет.
Jan Ouwens, создатель библиотеки, делится своим опытом и планами в новой статье.
Узнайте, какие проблемы решались разработчиком по мере развития Java, что было популярно до GitHub, и какие планы у Jan на будущее: https://jqno.nl/post/2024/06/01/looking-back-on-15-years-of-equalsverifier/
Подписывайтесь:
😌 @spring_aio
Переопределение методов equals() и hashCode() – непростая задача. Они должны соответствовать не только требованиям Java, но и используемому стеку технологий (например, JPA).
Библиотека EqualsVerifier помогает разработчикам проверить корректность переопределенных методов уже 15 лет.
Jan Ouwens, создатель библиотеки, делится своим опытом и планами в новой статье.
Узнайте, какие проблемы решались разработчиком по мере развития Java, что было популярно до GitHub, и какие планы у Jan на будущее: https://jqno.nl/post/2024/06/01/looking-back-on-15-years-of-equalsverifier/
Подписывайтесь:
Please open Telegram to view this post
VIEW IN TELEGRAM
tr ouwens
Looking back on 15 years of EqualsVerifier
In which I take a trip down memory lane.
На первый взгляд, выбор правильного Java-рантайма для вашего проекта на Spring Boot может показаться тривиальным. В конце концов, все популярные рантаймы основываются на коде OpenJDK и предлагают одинаковые программные интерфейсы.
Но не все рантаймы реализованы одинаково. В этой статье мы обсудим различные показатели, которые могут повлиять на ваше решение выбрать определенный дистрибутив Java для Spring Boot приложения.
🔗 https://habr.com/ru/companies/spring_aio/articles/819899/
#JVM #Java #SpringBoot
Please open Telegram to view this post
VIEW IN TELEGRAM
🐢 Неожиданное падение производительности при переходе на Spring Boot 3.3.0 👩💻
Hibernate подложил небольшую свинью, конвертируя JPQL в SQL. Внезапно, запрос поиска записей по списку id с передачей пустого списка деградирует в table full scan.
Однако, Hibernate пофиксил баг в течении 10 часов после поста в запрещенную в РФ соцсеть. Осталось дождаться новой версии Spring Boot, которая включит себе этот фикс.
🔗Подробнее читайте на Хабре
#SpringBoot #Hibernate #BreakingNews
Hibernate подложил небольшую свинью, конвертируя JPQL в SQL. Внезапно, запрос поиска записей по списку id с передачей пустого списка деградирует в table full scan.
Однако, Hibernate пофиксил баг в течении 10 часов после поста в запрещенную в РФ соцсеть. Осталось дождаться новой версии Spring Boot, которая включит себе этот фикс.
🔗Подробнее читайте на Хабре
#SpringBoot #Hibernate #BreakingNews
Please open Telegram to view this post
VIEW IN TELEGRAM
Друзья, напоминаем, что у нас есть чат (@spring_aio_chat), в котором вы можете:
Please open Telegram to view this post
VIEW IN TELEGRAM
Неблокирующие сервисы вчера: WebFlux, Coroutines и Loom.
"Неблокирующие сервисы" сегодня: DockerHub, IntelliJ IDEA Ultimate, Slack и другие.
#программисты_шутят
"Неблокирующие сервисы" сегодня: DockerHub, IntelliJ IDEA Ultimate, Slack и другие.
#программисты_шутят
Dynamic Projection в Spring Data JPA
Используя Spring Data, довольно часто могут возникать накладные расходы из-за получения из базы слишком большого количества полей. Чтобы решить эту проблему, мы можем объявлять методы с нативными запросами, DTO или проекциями для случаев, когда необходимо ограничить количество выбираемых полей. Но такой подход приводит к появлению множества очень похожих методов в репозитории. Например:
Чтобы решить эту проблему можно прибегнуть к использованию Dynamic Projection:
Подробнее о сценариях использования и компромиссах, на которые придется пойти используя Dynamic Projection, читайте в следующей статье: https://maciejwalkowiak.com/blog/spring-data-jpa-dynamic-projections/
Используя Spring Data, довольно часто могут возникать накладные расходы из-за получения из базы слишком большого количества полей. Чтобы решить эту проблему, мы можем объявлять методы с нативными запросами, DTO или проекциями для случаев, когда необходимо ограничить количество выбираемых полей. Но такой подход приводит к появлению множества очень похожих методов в репозитории. Например:
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findByName(String name); // выбираем из базы сущность со всеми её полями
List<ProductProjection> findPrjsByName(String name); //выбираем из базы ограниченный набор полей, указанный в некоторой проекции
List<ProductDto> findDtosByName(String name); //выбираем из базы ограниченный набор полей, указанный в некоторой DTO
}
Чтобы решить эту проблему можно прибегнуть к использованию Dynamic Projection:
public interface ProductRepository extends JpaRepository<Product, Long> {
<T> List<T> findByName(String name, Class<T> type);
}
Подробнее о сценариях использования и компромиссах, на которые придется пойти используя Dynamic Projection, читайте в следующей статье: https://maciejwalkowiak.com/blog/spring-data-jpa-dynamic-projections/
Maciejwalkowiak
Dynamic Projections with Spring Data JPA
Мы рады сообщить, что наше сообщество начинает обрастать экспертами, и мы будем знакомить вас с их мнением. Встречайте, Михаил Поливаха, коммитер Spring Data JDBC (Relational), не удержался от комментария по вопросу поддержки проекций в разных модулях Spring Data. Ниже прямая речь Михаила.
Надо сказать, что projection-ы, как функциональность, должна быть доступна во всех модулях spring-data. Вопрос в том, что еще не все модули ее поддержку реализовали до конца.
Наивный читатель мог бы предположить, что поскольку в spring-data-jdbc есть поддержка как interface based projection-ов, так и dynamic projection-ов, то вот это заработает:
Но данный код сгенерит ошибку глубоко в недрах JdbcQueryCreator-a:
Связано это с тем, что на данный момент spring-data-jdbc просто не умеет переваривать динамические проджекшены для инфтерфейсов 🙂
Про это мы знаем, бага на это дело пока нет, если он кому-либо важен - можем завести. Хочу также напомнить, что если есть какие-либо инициативы для нововведений в spring-data-jdbc - можно оставлять в комментариях или писать мне в ЛС.
Надо сказать, что projection-ы, как функциональность, должна быть доступна во всех модулях spring-data. Вопрос в том, что еще не все модули ее поддержку реализовали до конца.
Наивный читатель мог бы предположить, что поскольку в spring-data-jdbc есть поддержка как interface based projection-ов, так и dynamic projection-ов, то вот это заработает:
public interface MyEntityRepository extends CrudRepository<MyEntity, Long> {
<T> Optional<T> findProjectionByStatus(String status, Class<T> clazz);
}
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Accessors(chain = true)
@Table
public class MyEntity {
@Id
@EqualsAndHashCode.Include
private Long id;
private String status;
@CreatedDate
private Instant createdAt;
}
interface MyEntityInterfaceProjection {
String status();
Long id();
}
@Test
void whenDynamicProjectsAreInUseViaInterfaces_thenBlast() {
saveInitialEntity();
Optional<MyEntityInterfaceProjection> active = myEntityRepository.findProjectionByStatus("active", MyEntityInterfaceProjection.class);
Assertions.assertThat(active)
.isPresent()
.hasValueSatisfying(myEntityProjection -> {
Assertions.assertThat(myEntityProjection.id() != null && myEntityProjection.status().equalsIgnoreCase("active")).isTrue();
});
}
@NotNull
private MyEntity saveInitialEntity() {
MyEntity myEntity = new MyEntity();
myEntity.setStatus("active");
return myEntityRepository.save(myEntity);
}
Но данный код сгенерит ошибку глубоко в недрах JdbcQueryCreator-a:
java.lang.IllegalStateException: SELECT does not declare a select list
at org.springframework.data.relational.core.sql.SelectValidator.doValidate(SelectValidator.java:57)
at org.springframework.data.relational.core.sql.SelectValidator.validate(SelectValidator.java:49)
at org.springframework.data.relational.core.sql.DefaultSelectBuilder.build(DefaultSelectBuilder.java:207)
at org.springframework.data.jdbc.repository.query.JdbcQueryCreator.complete(JdbcQueryCreator.java:173)
at org.springframework.data.jdbc.repository.query.JdbcQueryCreator.complete(JdbcQueryCreator.java:66)
Связано это с тем, что на данный момент spring-data-jdbc просто не умеет переваривать динамические проджекшены для инфтерфейсов 🙂
Про это мы знаем, бага на это дело пока нет, если он кому-либо важен - можем завести. Хочу также напомнить, что если есть какие-либо инициативы для нововведений в spring-data-jdbc - можно оставлять в комментариях или писать мне в ЛС.
⚠️ Уязвимость в плагине JetBrains GitHub
Если вы используете плагин GitHub в IntelliJ IDEA или других продуктах JetBrains, советуем обновиться до последней версии и отозвать токены созданные IDEA в своем GitHub аккаунте.
Подробности в статье.
🔗 https://habr.com/ru/companies/spring_aio/articles/820819/
Если вы используете плагин GitHub в IntelliJ IDEA или других продуктах JetBrains, советуем обновиться до последней версии и отозвать токены созданные IDEA в своем GitHub аккаунте.
Подробности в статье.
🔗 https://habr.com/ru/companies/spring_aio/articles/820819/
Хабр
Уязвимость в плагине JetBrains GitHub
Была обнаружена новая проблема безопасности , затрагивающая плагин JetBrains GitHub , потенциально приводящая к раскрытию токенов доступа сторонним сайтам. Проблема затрагивает все IDE на базе...
🔧 Spring Data findAll антипаттерн
Spring Data Repository отличная концепция, позволяющая нам абстрагироваться от CRUD операций над domain entity. Достаточно объявить пустой интерфейс и унаследовать его, например, от ListCrudRepository или JpaRepository, если мы работем с JPA.
После этого нам сразу будут доступны основные методы работы с entity - save, update, findById, findAllById, findAll, и т.д. Но некоторые из этих методов могут привести к серъезным проблемам с производительностью и памятью, например метод findAll(). Давайте представим, что нам нужно найти всех Owner у которых есть животные c определенным именем и отсортировать по имени владельца. Поскольку мы находимся всего в одном шаге от вызова findAll() метода для «решения» этой проблемы, не пройдет много времени, пока кто-нибудь не предложит следующее решение:
Проблема здесь в том, что мы загрузили всю таблицу Post в память и потом начали фильтровать и сортировать данные, вместо того чтобы сделать это с помощью JPQL или SQL запроса за одно обращение к БД и загрузить в память только те данные, которые нам нужны в дальнейшем. Давайте посмотрим как мог бы выглядеть такой метод репозитория:
Если у нас в репозитории есть метод findAll(), мы должны понимать что рано или поздно, по мере роста команды, им может кто-то воспользоваться. Возможно следует определять базовый интерфейс репозитория вашем проекте самостоятельно и наследовать его от org.springframework.data.repository.Repository и подконтрольно наполнять его методами.
#SpringData #SpringTips
Spring Data Repository отличная концепция, позволяющая нам абстрагироваться от CRUD операций над domain entity. Достаточно объявить пустой интерфейс и унаследовать его, например, от ListCrudRepository или JpaRepository, если мы работем с JPA.
public interface OwnerRepository extends JpaRepository<Owner, Long> {
}
После этого нам сразу будут доступны основные методы работы с entity - save, update, findById, findAllById, findAll, и т.д. Но некоторые из этих методов могут привести к серъезным проблемам с производительностью и памятью, например метод findAll(). Давайте представим, что нам нужно найти всех Owner у которых есть животные c определенным именем и отсортировать по имени владельца. Поскольку мы находимся всего в одном шаге от вызова findAll() метода для «решения» этой проблемы, не пройдет много времени, пока кто-нибудь не предложит следующее решение:
public List<Owner> findOwnerByPetName(Collection<String> petNames) {
return ownerRepository.findAll()
.stream()
.filter(owner -> owner.getPets()
.stream()
.map(Pet::getName)
.anyMatch(petNames::contains)
)
.sorted(Comparator.comparing(Owner::getFirstName))
.toList();
}
Проблема здесь в том, что мы загрузили всю таблицу Post в память и потом начали фильтровать и сортировать данные, вместо того чтобы сделать это с помощью JPQL или SQL запроса за одно обращение к БД и загрузить в память только те данные, которые нам нужны в дальнейшем. Давайте посмотрим как мог бы выглядеть такой метод репозитория:
//derived method
List<Owner> findByPets_NameInOrderByFirstNameAsc(Collection<String> petNames);
//JPA query method
@Query("select o from Owner o left join o.pets pets where pets.name in ?1 order by o.firstName")
List<Owner> findOwnerByPetName(Collection<String> petNames);
Если у нас в репозитории есть метод findAll(), мы должны понимать что рано или поздно, по мере роста команды, им может кто-то воспользоваться. Возможно следует определять базовый интерфейс репозитория вашем проекте самостоятельно и наследовать его от org.springframework.data.repository.Repository и подконтрольно наполнять его методами.
#SpringData #SpringTips
🕓 Hibernate и спецификация JPA: приключение на 20 минут 24 часа
На прошлой неделе у нас был пост про внезапное падение производительности в Hibernate 6.5 на достаточно простом запросе. А сегодня вы можете прочитать историю этой проблемы от лица Гевина Кинга, создателя Hibernate.
Гевин Кинг рассказал, как возник этот баг, и как он повлиял на спецификацию JPA 3.2.
📚 Подробней читайте на Хабре
На прошлой неделе у нас был пост про внезапное падение производительности в Hibernate 6.5 на достаточно простом запросе. А сегодня вы можете прочитать историю этой проблемы от лица Гевина Кинга, создателя Hibernate.
Гевин Кинг рассказал, как возник этот баг, и как он повлиял на спецификацию JPA 3.2.
📚 Подробней читайте на Хабре
This media is not supported in your browser
VIEW IN TELEGRAM
По умолчанию в IntelliJ IDEA работают следующие комбинации клавиш:
1) ⌥ + ← (CTRL + ←) – передвинуть каретку к началу слова
2) ⌥ + → (CTRL + →) – передвинуть каретку к концу слова
3) ⇧ + ⌥ + ← (⇧ + CTRL + ←) – выделить слово до его начала
4) ⇧ + ⌥ + → (⇧ + CTRL + →) – выделить слово до его конца
5) ⌥ + ⌫ (CTRL + ⌫) – удалить слово с текущей позиции каретки и до его начала
Но мало кто знает, что эти шорткаты можно сделать еще удобнее!
Настройте их же для режима CamelHumps и IntelliJ IDEA начнёт понимать слова написанные в camelCase!
#IntelliJIDEA #Tooling #HotKeys
1) ⌥ + ← (CTRL + ←) – передвинуть каретку к началу слова
2) ⌥ + → (CTRL + →) – передвинуть каретку к концу слова
3) ⇧ + ⌥ + ← (⇧ + CTRL + ←) – выделить слово до его начала
4) ⇧ + ⌥ + → (⇧ + CTRL + →) – выделить слово до его конца
5) ⌥ + ⌫ (CTRL + ⌫) – удалить слово с текущей позиции каретки и до его начала
Но мало кто знает, что эти шорткаты можно сделать еще удобнее!
Настройте их же для режима CamelHumps и IntelliJ IDEA начнёт понимать слова написанные в camelCase!
#IntelliJIDEA #Tooling #HotKeys
Разработчики Каркаса Весеннего Ботинка утверждают, что эти фразы имеют смысл:
- "У меня не применяется совет контроллера"
- "Тебе нужно выстрелить событием"
- "Я сделал этот боб главным, чтобы мои анализы не провалились"
My controller advice did not apply
You need to fire an event
I made this bean primary in order to not to fail my tests
Они держат нас за дураков?
- "У меня не применяется совет контроллера"
- "Тебе нужно выстрелить событием"
- "Я сделал этот боб главным, чтобы мои анализы не провалились"
You need to fire an event
I made this bean primary in order to not to fail my tests
Они держат нас за дураков?
В мире Spring Boot отправка HTTP запросов к внешним сервисам является весьма распространенной задачей. Традиционно при достижении этой цели разработчики полагались на RestTemplate. Однако, по мере развития Spring Framework, на свет появился новый и более мощный способ обработки HTTP запросов: так называемый WebClient. Spring Boot 3.2 представил нам надстройку над WebClient, которая получила название RestClient.
RestClient предлагает нам более современные и интуитивно понятные способы взаимодействия с RESTful сервисами.
📚 Подробности в статье
Please open Telegram to view this post
VIEW IN TELEGRAM
Часто мы принимаем многие вещи на веру, не углубляясь в причину их происхождения.
Что же заставило Рода Джонсона (создателя Spring Framework), дать название «Spring» своему фреймворку? Если вы никогда об этом не думали, то эта статья из 2006 года именно для вас!
🔗 https://spring.io/blog/2006/11/09/spring-framework-the-origins-of-a-project-and-a-name
Please open Telegram to view this post
VIEW IN TELEGRAM
Spring Framework: The Origins of a Project and a Name
Level up your Java code and explore what Spring can do for you.
Roadmap для изучения Spring Boot: https://roadmap.sh/spring-boot. Сохраняйте, чтобы не потерять!
Будем рады обсуждению в комментариях!
Please open Telegram to view this post
VIEW IN TELEGRAM
Новый компилятор K2 в Kotlin. Часть 1
В новой статье эксперт сообщества Spring АйО – Михаил Поливаха рассмотрит новый компилятор К2 для Kotlin. Сначала он расскажет о том, какие проблемы K2 призван решить, а затем о других минорных улучшениях, которые были сделаны. Гайд по обновлению на новую версию будет опубликован в следующей части этой статьи.
📚 Подробней читайте на Хабре
В новой статье эксперт сообщества Spring АйО – Михаил Поливаха рассмотрит новый компилятор К2 для Kotlin. Сначала он расскажет о том, какие проблемы K2 призван решить, а затем о других минорных улучшениях, которые были сделаны. Гайд по обновлению на новую версию будет опубликован в следующей части этой статьи.
📚 Подробней читайте на Хабре