Иногда полезно освежить в памяти базовые принципы фреймворка. В Spring Framework центральное место занимает Bean. В своем видео Джош Лонг рассказывает об истории Bean и его жизненном цикле.
#SpringTips #SpringBoot
📱 https://www.youtube.com/watch?v=Z5hxolai4Tk
Подписывайтесь:
😌 @spring_aio
#SpringTips #SpringBoot
Подписывайтесь:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3👏2
🕐 Тонкое управление Scheduled задачами в Spring
Какими способами можно настроить время и условие запуска Scheduled задач в Spring?
Первый способ - через
Но в таком варианте, мы управляем только условием запуска, но не можем настроить переодичность.
Другой вариант, это объявление cron expression в пропертях:
Но как тогда в таком случае отключить джобу? В качестве cron expression можно использовать дефис(-), что означает, что джобу запускать не нужно вовсе. И тогда мы обходимся без явного перечисления профилей в
Такой подход особо полезен при использовании spring-cloud-config, тогда нет необходимости делать передеплой приложения, чтобы выключить, или донастроить джобу. Нужно только не забыть повесить
#SpringBoot #SpringTips
Какими способами можно настроить время и условие запуска Scheduled задач в Spring?
Первый способ - через
@Profile
над сервисом, в котором объявлена задача, чтобы указать профили, в которых она должна (или не должна) запускаться.
java
@Profile("test,!prod")
class Teapot {
@Scheduled(cron = "0 15 10 15 * ?")
void makeTea() {
log.info("I'am a teapot.");
}
}
Но в таком варианте, мы управляем только условием запуска, но не можем настроить переодичность.
Другой вариант, это объявление cron expression в пропертях:
#application-test.properties
teapot.make_tea.cron=0 15 10 15 * ?
@Scheduled(cron = "${teapot.make_tea.cron}")
void makeTea() {
log.info("I'am a teapot.");
}
Но как тогда в таком случае отключить джобу? В качестве cron expression можно использовать дефис(-), что означает, что джобу запускать не нужно вовсе. И тогда мы обходимся без явного перечисления профилей в
@Profile
.
#application-prod.properties
teapot.make_tea.cron=-
Такой подход особо полезен при использовании spring-cloud-config, тогда нет необходимости делать передеплой приложения, чтобы выключить, или донастроить джобу. Нужно только не забыть повесить
@RefreshScope
на класс.#SpringBoot #SpringTips
👍10👌5🔥3
🔧 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
👍23✍5👀3👎2😴2