SC24EP03 Работа с базами данных - Разработка проектов со Spring

Поділитися
Вставка
  • Опубліковано 17 січ 2025

КОМЕНТАРІ • 84

  • @ratsmasher
    @ratsmasher 10 місяців тому +30

    Один из немногих разработчиков на ютубе, который так подробно и продвинуто обьясняет разработку приложений на спринг и все что с ним связано. У других максимум найдешь создание простых CRUD приложений, а тут на канале обхват тем и фич коллосальный. Очень много полезной инфы узнал из роликов!

  • @tedbear6330
    @tedbear6330 5 місяців тому +5

    Отличные уроки! Для всех кто пользуется Spring Boot 3.3.2: по мимо тех зависимостей, которые добавил Александр, нужно также добавлять flyway-database-postgresql для работы с postgresql из flyway. Версию можно неуказывать Dependecy manager сам разберется

  • @Devivl
    @Devivl 10 місяців тому +5

    Потрясающий универсальный подарок на 8 марта - годный контент от сельского джависта :)
    Твоих любимых и дорогих людей с праздником, Саня!
    Добра, любви, тепла и всего самого хорошего!

  • @ArtemShishkinV
    @ArtemShishkinV 10 місяців тому +4

    Спасибо за урок!
    Таймкоды, вдруг кому-то полезно будет:
    00:00 - Об основных понятиях урока(JPA, Hibernate, Spring Data JPA, Flyway)
    03:54 - Подключение зависимостей
    04:36 - Описание структуры БД
    07:42 - Маппинг сущности в коде на сущность в БД (@Entity)
    14:08 - Создание @Repository
    19:00 - Настройка подключения к БД
    23:00 - Баг-фикс изменения товара(update в БД)
    26:30 - Вводная информация по созданию пользовательских запросов к БД
    28:00 - Cоздание пользовательского запроса к БД по названию метода в репозитории
    35:45 - Создание пользовательского запроса к БД с использованием JPQL(@Query, @Param)
    38:50 - Создание пользовательского нативного запроса к БД (nativeQuery = true)
    39:50 - Создание пользовательского именованного запроса (@NamedQueries)
    44:00 - Добавление возможности фильтрации списка товаров на UI
    48:25 - Подведение итогов

  • @Константин-ы9к
    @Константин-ы9к 9 місяців тому +1

    Отлично. Смотрю дальше.

  • @МихаилМихаил-ф7у
    @МихаилМихаил-ф7у 3 місяці тому +1

    Огонь, едем дальше!

  • @johnconnor3553
    @johnconnor3553 10 місяців тому +1

    Счастья и здоровья тебе,добрый человек!

  • @airat2010
    @airat2010 8 місяців тому +2

    Это очень качественный и от настоящего профессионала, контент!

  • @Boraldan
    @Boraldan 10 місяців тому +1

    Всё по полочкам разложил, спасибо.

  • @Wemmer123
    @Wemmer123 10 місяців тому +2

    Спасибо ОГРОМЕННОЕ.

  • @krutaxe
    @krutaxe 10 місяців тому +2

    Супер! Спасибо) 🎉

  • @AlexSmile-y2x
    @AlexSmile-y2x 9 місяців тому +3

    Спасибо, Александр! Очень крутой цикл видео! И уровень разработки крутой. Отдельное спасибо за внимание к каждому комментарию, это очень приятно) Вы очень хорошее дело делаете!
    При просмотре не понял пару деталей:
    1) зачем везде this? он вроде бесполезен в нормальном коде, где имена полей никогда не совпадают с именем аргумента
    2) зачем такое именование полей БД? это же боль для стороннего программиста, тестировщика, DBA, аналитика
    3) зачем примитивы в полях и аргументах? Это будущие NPE при взаимодействии слоев, сервисов, десериализации и вдобавок дефолтное значение в отличии от ссылки, несущее кучу неочевидных багов потенциально
    4) зачем возвращать из репозитория Iterable? не лучше ли наследовать более подходящий интерфейс вместо Crud (JpaRepository например)
    5) почему не использовались read only транзакции над методами чтения? будет лишний dirty checking при каждой выборке, а это создание, копирование и сравнение массивов всех полей всех сущностей каждый раз под капотом
    6) операция patch тут разве правильно реализована? получается в реальности put (осуществляется замена всех полей сущности, а патч подразумевает только модификацию тех, которые были заданы), более того такая реализация неконсистентна со структурой сущности (структура изменится, а патч нет - придется руками менять при каждой модификации структуры)
    7) почему обработка ошибок рест клиента через try-catch, ProblemDetail и cast к списку? выглядит как костыль. Тут разве не просится получение результата в виде Either объекта и дальнейшая обработка? использование в коде CRUD app явного cast, instanceof или reflection - плохой звоночек. Да и в целом не понятно почему не использовался HTTP Interfaces, там отличная поддержка для RestClient в новых версиях спринга
    8) почему для Rest service не использовался @RestControllerAdvice?
    9) почему вместо возврата List не возвращается Page/Slice? это и обертка над списком значений с метаданными и сразу готовя пагинация с сортировкой
    10) почему не отключен open-in-view? мы же не дергаем прокси из контроллеров, но зато имеем из-за этого открытую сессию хибера на уровне контроллера, а не там, где она реально нужна. Стандартный антипаттерн вроде

    • @shurik_codes
      @shurik_codes  9 місяців тому +2

      Ох, сколько вопросов)
      1. На мой взгляд упрощает читаемость кода, сразу понимаешь, где обращение к членам класса, а где - к локальным переменным. Но, возможно, это сила привычки
      2. Чтобы по названию можно было определить, какую роль выполняет тот или иной элемент. Снова привычка
      3. Ни разу не сталкивался с какими-либо проблемами из-за использования примитивов, стараюсь использовать именно примитивы там, где это возможно
      4. Iterable используется, потому что возвращается по умолчанию, ну и от него требуется только возможность использования итератора. Не вижу смысла в использовании более специфичного JpaRepository в ситуациях, когда хватает функциональности более общего CrudRepository
      5. Тут да, забыл, банально за всем не уследишь
      6. В том-то и дело, что PUT подразумевает полную замену всех свойств сущности (id, title, details), иными словами замену всей сущности, а в запросе фигурируют только свойства, которые мы можем изменить (title, details). Именно поэтому PATCH, а не PUT. PUT замещает объект, а PATCH - изменяет свойства объекта. Для соблюдения консистентности можно воспользоваться версионированием API, но это я буду рассказывать вообще в отдельном ролике.
      7. try/catch - вполне стандартный подход, ProblemDetail - опять же стандартный способ описания HTTP-ошибки в REST API (да, в черновике IETF, но лучше, чем что-то самописное), а каст нужен, т.к. список ошибок передаётся одним из свойств свободной формы. Да, можно было на стороне REST API сформировать строку ошибки и передать её в details. Использование HTTP-интерфейсов - это уже углубление, которое лучше разобрать в отдельном ролике.
      8. Потому что достаточно и обычного @ControllerAdvice
      9. Опять же углубление, про которое нужно отдельно рассказывать, у меня и так ролики получаются большие, а если раскрывать каждую деталь, то они будут ну очень большими
      10. Банально потому что забыл, т.к. на практике давно MVC-приложений не пишу

    • @AlexSmile-y2x
      @AlexSmile-y2x 9 місяців тому

      @@shurik_codes Большое спасибо за такой детальный развернутый ответ!)) Ролики у Вас совсем не большие, имхо, максимально лаконично все уложено, даже чрезмерно где-то, а по такой теме 2-3 часа видео - это норма) тот кто смотрит ролик длиной 1ч, тот с удовольствием посмотрит и трехчасовой и пяти, будьте уверены)) Недаром на UA-cam при фильтре определяющие значения 4 мин и 20 мин, они проводили исследования по этому вопросу и 20 мин являются чертой, выше которой человек смотрит практически любой длины видео, а тот кто не смотрит длинные, тот 20 минут не осиливает в свою очередь чаще всего, самая ленивая группа смотрит менее 4 мин всегда (но это касается не только лени, но и типа видео, разумеется)

  • @Евгений-ы4м3ж
    @Евгений-ы4м3ж 9 місяців тому +1

    Очень понятно и при этом хорошо раскрывается тема. Спасибо!

  • @itmaker1821
    @itmaker1821 9 місяців тому +1

    Лайк циклу, лайк ролику, лайк автору =)

  • @vadimkharovyuk7660
    @vadimkharovyuk7660 10 місяців тому +1

    Спасибо за урок . Лайк / подписка 🙌

  • @ДмитрийТищенко-е9ъ
    @ДмитрийТищенко-е9ъ 9 місяців тому +1

    Отличный материал!!!

  • @hurricane-rus
    @hurricane-rus 7 місяців тому +2

    Еще важно отметить, что валидация должна делаться в dto, а в entity приводятся только наборы полей, которые мапятся на поля таблиц БД. Скорее всего для экономии времени в проекте это совмещено, но это плохая практика на реальном проекте, потому что приводит к спагетти-коду.
    Когда идет подключение к БД, в настройках конфигурации должен быть указан профиль, иначе ничего не запустится. Best practice - отдельный ямл без постфиксов, где указывается активный профиль, и ямл под каждое отдельное окружение (это будет работать, потому что специализированные ямлы будут наследовать все данные из дефолтного ямла).

  • @alekseizhitenev6020
    @alekseizhitenev6020 6 місяців тому +1

    спасибо)!

  • @ChinukB12
    @ChinukB12 10 місяців тому +5

    Саша, спасибо за контент
    Подскажи, когда планируешь и планируешь ли снимать создание рест приложений с использованием webflux?

    • @shurik_codes
      @shurik_codes  10 місяців тому +2

      В 7 ролике цикла будет

  • @denisthestudent
    @denisthestudent 8 місяців тому +1

    Спасибо!

  • @goodvideobro
    @goodvideobro 10 місяців тому +1

    крутой ролик получился

  • @user-007-1
    @user-007-1 10 місяців тому +2

    Чётко
    Планируется ли ролик по интеграционному тестированию этого приложения?
    По юнит тестам много инфы, а вот хороший пример настойки тестконтейнеров и тестирования бд/брокеров сообщений найти не удалось

    • @shurik_codes
      @shurik_codes  10 місяців тому +1

      В 5 ролике будет

  • @Hocorend
    @Hocorend 8 місяців тому

    Спасибо за видео.
    А я думал, что без реализации репозитория в классе, нужно @Repository ставить над интерфейсов, оказалось оно там и не нужно.
    Этот урок оказался коротким, но даже тут узнал что-то новое и крайне полезное, но без заранее подготовленных знаний по работе с БД у новичков будет темный лес)) Но иначе бы пришлось делать урок на пару часов, например, нет ни слова про отношения OneToMany и т.д.

    • @СемёнСердюков-д7р
      @СемёнСердюков-д7р 6 місяців тому

      Если я правильно понял о чем речь, то если не ставить аннотацию то не будет в логах специфичные ошибки показывать для бд. А так можно хоть @Component поставить

  • @explo9087
    @explo9087 10 місяців тому +1

    Спасибо за очень информативные видео. Может сделаете видео как правильно загружать, хранить и получать файлы с сервера, например картинки через контролеры, тоесть чтоб Product был еще и с картинкой )

  • @markostr
    @markostr 10 місяців тому +1

    Все прекрасно у Вас получается! Спасибо ! Очень доходчиво. Но будет ли Join в запросах хотя бы один-ко многим из двух таблиц? И как сериализовать чтобы подучился Json с вложеными блоками в таком случае? И вообще как работает сериализация при запрсах nbgf JOIN итп. Оочень нужно...

    • @shurik_codes
      @shurik_codes  10 місяців тому

      В рамках этого цикла роликов - нет, отдельно надо подумать

  • @a1K04ek0v
    @a1K04ek0v 9 місяців тому +1

    Александр, спасибо вам за эти замечательные обучающие ролики, все лаконично и на современном стэке! Разрешите задать вопрос, в чем смысл в классах обращаться к инжектируемым сущностям через this, без него ведь то же все будет корректно работать? Вероятно, это просто ваш стиль программирования направленный на поддержание кода в более структурированном и понятном виде))

    • @shurik_codes
      @shurik_codes  9 місяців тому

      Да, это стиль программирования, сразу видно, где обращение к локальным переменным, а где - к свойствам класса

  • @kazbowski
    @kazbowski 10 місяців тому +2

    Привет! Спасибо за твои видосы :) Хочу предложить тему для ролика: OTP (one time password) в spring security. По ней достаточно мало материала, а тот что есть - сделан очень коряво. Я сейчас сам начал пытаться реализовать данную тему, и понял, что это прям очень сложно выглядит (приходится переопределять usernamepasswordauthenticationfilter и делать прочие шаманства, что реализовать безопасный ввод кода). Очень бы хотелось увидеть твою реализацию по данной теме. Надеюсь - заинтересует, спасибо!

    • @shurik_codes
      @shurik_codes  10 місяців тому

      Постараюсь такой ролик записать

  • @odtour
    @odtour 3 місяці тому

    47:57 Почему знак вопроса - это процент? И зачем вообще их туда добавлять, т.е. почему без них не работает?

    • @shurik_codes
      @shurik_codes  3 місяці тому +1

      Знаки процента, банальная оговорка. Добавлять нужно для нестрогого сравнения по тексту

  • @romanovichihin2429
    @romanovichihin2429 7 місяців тому

    Комент для продвижения

  • @temaMalina
    @temaMalina 10 місяців тому +1

    Александр, здравствуйте, огромное спасибо за ролики! А вы не планируете в других роликах, вне цикла, рассмотрение фреймворка Camel? И еще вопрос, а вы использовали restclient, а feignclient в своей работе используете?

    • @shurik_codes
      @shurik_codes  10 місяців тому

      OpenFeign не использую, Camel, скорее всего, будет

  • @odtour
    @odtour 3 місяці тому

    28:20 Где настроить эти подсказки?

    • @shurik_codes
      @shurik_codes  3 місяці тому +1

      Оно уже сконфигурировано в IDEA Ultimate

  • @eapashkov
    @eapashkov 10 місяців тому +2

    Александр, напоминай пожалуйста, что не стоит писать select * from, тебя же новички смотрят)

  • @AlLu-u7v
    @AlLu-u7v 10 місяців тому +1

    как вариант еще можно фильтрацию реализовать через findByTitleContainingIgnoreCase(String filter);
    не нужно будет делать проверку на null и blank

    • @shurik_codes
      @shurik_codes  10 місяців тому +1

      Можно и так, я привычен к failfast-стилю

  • @ИгорьПавлов-ч1ф
    @ИгорьПавлов-ч1ф 8 місяців тому

    всё прекрасно, одно маленькое замечание не у всех ультимейт версия идеи.

  • @eddyz5780
    @eddyz5780 3 місяці тому

    Привет. У меня возник вопрос по поводу баз данных. Что делать, если у нас есть несколько сущностей и они связаны между собой. Как сохранить эту связь между сервисами? Нужно создавать какой-то отдельный модуль для сущностей и настраивать там связи? Или просто передавать dto и как-бы не испольщовать аннотаци onetomany и т.д. ? Или в каждый сервис копировать сущности ? просто если нам не нужны все сущности в сервисе ?
    Вот например мы создаем сервис по формированию заказа, по идеи нам нужен товар, продавец и покупатель, но у покурателя наримеи есть еще поставщики, которые не нужны нам в этом сервисе. Как поступать в таких моментах ?

  • @akalavan5395
    @akalavan5395 9 місяців тому

    Хотел уточнить, какой вариант запроса лучше использовать на практике или в какой ситуации лучше использовать тот или иной метод создания запроса?

    • @shurik_codes
      @shurik_codes  9 місяців тому

      Использование названий методов - для самых простых вопросов, EntityManager - для самых сложных. В целом никто не запрещает для всех случаев использовать EntityManager. Тут характеристика лучше-хуже не совсем уместна)

  • @azsaliance-bw4ui
    @azsaliance-bw4ui 10 місяців тому +2

    Чтобы запрос был более красивым поможет настройка
    spring.jpa.properties.hibernate.format_sql=true

  • @dariyershov8152
    @dariyershov8152 9 місяців тому

    Как называется тема на intellij idea? Понравился визуал значков и сочетание цветов

  • @Denys.Stoianov
    @Denys.Stoianov 10 місяців тому

    пропустил момент почему используется не паблик схема в преимущества использование не по дефолту и в чем преимущества использования префиксов "t_table _name" и с колонками тоже, это сделано намеренно в целях наглядности, наверное

    • @shurik_codes
      @shurik_codes  10 місяців тому

      Про схему: 5:25, префиксы для наглядности, да

  • @AlexPlanetEarth
    @AlexPlanetEarth 10 місяців тому

    Интересно как реализован save при завешении транзакции, ведь как то где то должен отслеживаться список измененных объектов?
    Получается есть какой то менеджер объектов которых сохраняет ссылку на объект/егопрокси пока не произойдет завершение транзакции?
    Интересно как это в хибере и не только реализуется под капотом.

    • @SlevySoddik
      @SlevySoddik 10 місяців тому +1

      Persistence Context

    • @AlexSmile-y2x
      @AlexSmile-y2x 9 місяців тому +2

      Cущесвует несколько уровней кэширования в Hibernate:
      - на уровне сессии(по умолчанию активно)
      - на уровне фабрики сессий(по умолчанию не активно)
      Кэширование на уровне сессии представляет из себя поле в объекте Session, являющееся объектом PersistenceContext, содержащее, строго говоря, набор мап и метаданных с информацией об активных entity.
      Основная из этих мап - поле HashMap entitiesByKey, где K - id сущности(объект EntityKey, содержащий id сущности, хэш и т.н. EntityPersister(специфичный преобразователь ORM, закрепленный за текущим типом entity)), а V - сама сущность.
      Т.о. при попытке получить сущность Hibernate сперва получает ее из этой мапы, а если в ней нет, то получает из DB, после чего добавляет в мапу, чтобы при следующем поиске не идти снова в DB.
      В другой мапе также инициализируется массив всех полей persistent объекта (добавленного в кэш), а при завершении транзакции происходит сравнение значений из этого массива с текущими значениями и если они не совпадают, то сессия считается "грязной"(были изменения объекта в ее ходе) и происходит дополнительный апдейт в БД. Этот механизм (dirty-checking'а, а не самого кэша) можно отключить, если использовать транзакцию с флагом read-only, тогда все апдейты нужно делать явно.

    • @AlexPlanetEarth
      @AlexPlanetEarth 9 місяців тому

      @@AlexSmile-y2x СпасиБо за развернутый ответ!

  • @viewer_evgeniy
    @viewer_evgeniy 10 місяців тому

    Здравствуйте, а для создания таблицы if not exists уже не нужно указывать?

    • @kazbowski
      @kazbowski 10 місяців тому

      Это не обязательные атрибуты

    • @shurik_codes
      @shurik_codes  9 місяців тому

      Можно указывать, для схемы я указываю, т.к. FlywayDB сама создаёт схему ЕМНИП, и я не хочу конфликта при выполнении скрипта

  • @ровойт
    @ровойт 5 місяців тому +2

    сделайте какой-то новый проект более интересный и больший - когда будут новые уроки

  • @alexv1549
    @alexv1549 7 місяців тому

    А у меня упорно не стартует ваш проект. WARN на flyway и на отсутствие коннекта к БД, раз я JPA и Postgre в POM указал

    • @shurik_codes
      @shurik_codes  7 місяців тому

      А параметры подключения к БД?

    • @alexv1549
      @alexv1549 7 місяців тому

      @@shurik_codes если имеется ввиду доп настройки в yaml/property или compose то таковых нет, postgre в Docker запустился нормально. я просто запустил ваш проект с git. Docker только вчера поставил, до этого в глаза его не видел

    • @t0tom427
      @t0tom427 4 місяці тому

      Наверное уже не надо, но у меня была такая проблема и решил ее добавлением flyway-database-postgresql зависимости в maven, может кому поможет

  • @yasha64000
    @yasha64000 9 місяців тому +2

    без зависимости flyway-database-postgresql кидал Unsupported Database

    • @shurik_codes
      @shurik_codes  9 місяців тому

      Код к ролику: github.com/alex-kosarev/sc24/tree/SC24EP03-spring-data-jpa всё работает без этой зависимости

    • @lightning_trade_official
      @lightning_trade_official 6 місяців тому

      спасибо большое! думал щас на 2 часа застряну с этой проблемой

    • @КатеринаКатерина-э9э
      @КатеринаКатерина-э9э 5 місяців тому

      Спас ваш комментарий! Спасибо)
      А не подскажите почему без нее не работало?

  • @eapashkov
    @eapashkov 10 місяців тому

    Ты на мак пересел?

  • @dmitriykim7741
    @dmitriykim7741 5 місяців тому

    а каким образом определяется url для базы данных? (jdbc:postgresql://localhost:5432/catalogue). Просто определенный шаблон, который начинается с "jdbc:postgresql", а хост можно указать любой? И "/catalogue" здесь указывается название схемы?

    • @shurik_codes
      @shurik_codes  4 місяці тому

      jdbc:://:/, подробнее: docs.oracle.com/javase/tutorial/jdbc/basics/connecting.html

  • @ivshapovalov
    @ivshapovalov 6 місяців тому +1

    Огонь. Огромное спасибо