вот такой формат очень хорош, когда видно реальный код, и разбираются ошибки. Спасибо!
@maxlich91397 жыл бұрын
За обзор кода респект. Это ультра-удобно, наглядно, полезно, хорошо запоминается и позволяет хорошо понять тему, разобраться в ней. Продолжайте в том же духе, Сергей.
@TheHNKNTOS9 жыл бұрын
Сергей большое вам спасибо за ваш труд. Формат видео действительно отличный.
@andriizarazka86719 жыл бұрын
Здравствуйте Сергей! Отличное видео, но неплохо было б если бы Вы выложили это исходник. Хотелось посмотреть как всё организовано, так как в инете нет толковых примеров.
@kekuh19 жыл бұрын
Уникальный контент для студентов не имеющих опыта разработки реальных проектов ! Много новых фишек вынес, очень интересно, спасибо !
@аавыф-б4о3 жыл бұрын
Спасибо, всё понятно и системно. Объясняется так продуманно и прозрачно, что даже мне, 1Снику (на жаве никогда не писал) всё воспринимается как родное. И куда, и что, и зачем именно так, и почему, и что будет, и как ты потом будешь читать пустые логи, с внезапно и взрывообразно переполненными коннекшнами на скуле, посреди ночи... У нас только переменные длиннее, мы не паримся, у нас это даже в гайдлайнах. Типа, пусть занимают пол-экрана. Читается бегло текст любого размера (по кол-ву букв) - имеет значение только количество перечисленных сущностей. Но в жаве областями видимости управлять гораздо удобнее - появляется возможность сократить имена и при этом не пересечься. Поэтому у нас длиннее. Умножить количество всех объектов что отображены в БД, на количество возможных DAO-имплементаций для любого возможного скуля... Нуда, такое. Где ORM-объектов 1500 штук в системе - там легко может стать и 5000 через полгода, за счет реализаций дополнительных хотелок заказчика. Было 7500 DAO-объектов (по 5 на каждый ORM-объект)... Стало 25000. Мда...
@woodscrock4 жыл бұрын
Из 2020 -> актуально :) Спасибо!!!!
@АлександрДворцов-ш1б9 жыл бұрын
Сергей, давайте продолжение! Материал у вас действительно уникальный!
@maksimpetrov1099 жыл бұрын
Отличный формат. Очень понравилось. Все наглядно.
@abdullahabbas37298 жыл бұрын
Sergey очень доступно объясняете
@tedirensmusic8 жыл бұрын
Добрый день! Подскажите. В проекте используется jpa. Одна из сущностей содержит поле, которое в случае какого-то действия должно увеличиваться или уменьшаться на указанное число. При использовании SQL это выглядело бы как-то так: SET field = field + 1. Как подобное реализовать используя ORM? Если я просто вызову "setter" на сущности, то в случае если кто-то в это же время попытается изменить эту сущность в другом потоке, то я потеряю часть данных ибо "last commit wins". Интернеты рекомендуют использовать версионирование. Но это просто приводит к исключению StaleEntityException в случае коллизии. А мне нужно просто увеличить поле. Спасибо!
@Alf_GS3 жыл бұрын
Добрый день, Сергей! Подскажите как в реализации с DAO решить такую проблему (вынесем за скобки актуальность паттерна и подхода в целом, в моём случае он актуален :) ). Добавляем/меняем две реляционно-связанных сущности, и получается, что нужно обратиться к двум разным DAO-классам для их инсерта/апдейта. 1. На каком уровне это делать? На доменном? Или инкапсулировать в DAO одной из сущностей добавление/изменение второй? Не сильно ли тогда DAO одной сущности распухнет? 2. Как корректней объединить это в одну транзакцию? Тогда нужно выносить коннект и понимание транзакции из DAO выше, в доменную логику? 3. Если в транзакции участвует 3-я сущность, которая реляционно не связана с предыдущими двумя, на каком слое манипуляции с ней должны происходить в случае если в ответе на первый вопрос была инкапсуляция в DAO? В этих двух постах под этим видео детальней схожие вопросы звучат, но ответов, к большому сожалению, не сохранилось :( kzbin.info/www/bejne/nJ2wd3x5pbWZmas&lc=Ugj7RHi45uXgCXgCoAEC.84w0D5FXbAo7-KxAXGYTlr kzbin.info/www/bejne/nJ2wd3x5pbWZmas&lc=UgiKK3fbo7VNgHgCoAEC
@skisportsergievposad56003 жыл бұрын
Сергей,вы как всегда Немчинский , и как всегда лучший!)
@user-sankarsana8 жыл бұрын
Очень познавательная лекция! Спасибо! Есть несколько вопросов: - Каждый раз (в каждом методе) нужно создавать и закрывать connect??? Это же затратно по времени и ресурсам? - Будет ли продолжения про БД, леера, тесты (очень важно с реальными примерами, как здесь)? - Посоветуйте, пожалуйста исходный код приложения, для примера. Уровня hello world, как Вы говорите. Где есть ui, бизнес логика, база данных. И где всё правильно организованно. Очень не хватает подобного уровня лекций. Большое спасибо!
@аавыф-б4о3 жыл бұрын
Мы, например, передавали коннект в параметрах некоторых методов, например конструкторов, и он мог быть равен null (т.е. еще не установлен). А конструктор брал уже установленный, либо устанавливал новый коннект (если null) и приравнивал его в параметр. Т.е. т.о. мы как бы "закешировали" коннект в параметре между вызовами. Потом мы привязали конеект к пользовательской сессии. 1 пользователь (точнее сессия) - 1 коннект. Это энтерпрайз был, не веб.
@sergeyshestakov4936 Жыл бұрын
Спасибо, нужно было посмотреть как рисовать uml, в итоге залип и до сюда досмотрел )
@user-olegmish3 жыл бұрын
@Sergey Nemchinskiy Спасибо за видео! После просмотра сюжета возник следующий вопрос. Может более изящьным решением было разделение DAO слоя на два слоя. Слой DAO и слой Service? В слое ДАО мы работаем с SQL, а в сервис слое управляем транзакцией.
@аавыф-б4о3 жыл бұрын
нет, Сергей сказал что более изящным решением было бы реализовать 1 универсальный (независимый от вида скуля) DAO-объект на каждый 1 ORM-объект, и сделать их так чтоб не менять ни один из них при переезде на другой скуль. Т.е. не использовать специфические для данного скуля фишки, а только универсальные, чтоб на любом скуле работало.
@tzofeolam6 жыл бұрын
Закрывать ResultSet самому обычно не надо. Он прекрасно закрывается автоматически во время закрытия Statement или PreparedStatement. В свою очередь Statement и PreparedStatement так же закрываются автоматически после закрытия Connection. Разница тут в том, что обычно мы хотим продолжать использовать Connection после окончания работы с конкретным Statement или PreparedStatement (поэтому их нам нужно закрывать руками) но после получения ResultSet старый Statement или PreparedStatement нам обычно уже не нужен и мы хотим закрыть их оба, что можно сделать закрыв лишь Statement или PreparedStatement.
@mmaltsau8 жыл бұрын
Здравствуйте, Сергей. Спасибо за видео. Появился такой вопрос: Вы говорите, что уровень бизнес логики не должен иметь зависимости на всякие sql штуки. В моем проекте появилась необходимость организовать транзакции. Чтобы реализовать это, необходимо иметь один connection для нескольких DAO классов, т.к надо для connection установить autocommit(false), после выполнения запросов сделать connection.commit(), а в случае ошибки сделать connection.rollback(). Если каждый dao класс будет получать свой connection то никакое connection.rollback() не сработает. Вот и получается что у меня connection создается на уровне бизнес-логики и устанавливается через конструктор в классы dao. Как можно красиво решить эту задачу, чтобы бизнес-логика не зависела от connection?
@аавыф-б4о3 жыл бұрын
Сергей, очень (ну прям ОЧЕНЬ) нравится как вы проводите аудит кода, смотрится от корки до корки не перематывая. А еще такие ролики есть/будут на канале? Вот прям с IDE-шкой, кодом, и вами?
@viktor14639 жыл бұрын
Супер спасибо , жду про тестирование :)
@georgii63249 жыл бұрын
Сергей, я заметил, что в этом примере, в Domain Layer'e находятся классы, которые вытаскиваются из DAO. Эти классы что из себя представляют? DTO или Domain Models? Если Domain Models, то они же должны доставаться из Repository? А если DTO, то значит они не содержат никакой бизнесс логики и нету им места в Domain Layer'e? Я немного запутался :) И еще один вопрос, если есть Domain Models, то это значит, что приложение построено по архитектуре DDD или необязательно? В обычном 3/4-layer'ном приложении вроде нет Domain Models, там всей бизнесс логикой заправляют "процедурные сервисы". P.S. Сорри за много букав :)
@АлександрБондарев-ъ7ф6 жыл бұрын
Хороший формат. Понятная подача информации.
@Андрій_Ляшенко2 жыл бұрын
Супер інформативне!)
@ВасилийГоловко-д9и7 жыл бұрын
В блоке finally отдельно делаем для каждого close блок try? Для coonection, для statement и для resultSet. Т.к. если будет один блок try для их закрытие, и например выпадет exception для connection, то try прервется и не выполнится закрытие для statement и для resultSet
@adelkhalitov59843 жыл бұрын
По поводу дао, касаемо метода дао и открытие соединении там очень интересно. Но только что если это транзакционный запрос в рамках одного инстанта и нескольких дао сущностей. Тем более любой запрос на чтение тоже в рамках данной транзакции. Я к тому что это накладно по поддержке. Я понимаю транзакция в рамках 2х микросервисов, можно что то подумать, там стоит наверное акцентировать внимание на 2х разных транзакциях в разных бд. Но в рамках одного инстанта, зачем??? Можно больше ценности пожалуйста, очень интересно. И если запрос синглтон почему бы не отдать соединение синглтон?
@alexpepper21469 жыл бұрын
на 9:45 где говорится про ексепшин из препаред стетмента, мы не попадём в final где resultSet null, но мы туда попалибы если бы был ексепшин при получении resultSet
@GAVVVR9 жыл бұрын
05:15 я правильно понял, что проблемы будут только если Connection сделать статическим полем? так то Connection будет отдельным для каждого объекта класса DAO.
@Otruiniy_Grybochok9 жыл бұрын
такой вопрос если нам не нужно обрабатывать исключения которые могут вылететь при закрытии rs, можно ли просто сделать catch по Exception и тогда по идее все исключения которые могут вылететь из rs.close(); будут перехвачены .
@sedilpioestma88028 жыл бұрын
Сергей, можете пожалуйста объяснить какой смысл паттерна DAO в данном контексте? Везде пишут что DAO - это паттерн инкапсулирующий хранилища и механизмы доступа к ним: благодаря зависимости от интерфейсов мы можем подставлять файловые хранилища, различные виды баз данных, XML и так далее. Посмотрев ваше видео и почитав комментарии я понял вас так: мы создаем классы DAO и классы Entity, при этом мы избавляемся от интерфейсов, фабрики DAO и множества реализаций типа PostreSQLDAO и так далее. А что осталось в сухом остатке? Просто обычные классы, которые инкапсулируют SQL запросы и являются точкой взаимодействия с БД. Это уже не дотягивает до паттерна...
@maxlich91397 жыл бұрын
А есть что-нибудь по юнит-тестированию и логированию? Если нет, то расскажите, пожалуйста об этом, Сергей.
@КонстантинКонашенков-и2ф6 жыл бұрын
А не проще было бы сделать DAOFactory -> PostgreSqlDAOFactory. И уже PostgreSqlDAOFactory будет отдавать коннекшен ?
@ОльгаЛисицына-у1ж5 жыл бұрын
Присоединяюсь к вопросу
@АлексейМешков-з8э5 жыл бұрын
Тоже интересно
@SergeyNemchinskiy4 жыл бұрын
извините. а зачем? Чтобы что?
@Alellas9 жыл бұрын
Сергей, возможно я еще не все видео посмотрел, но во многих вы обходите стороной такую, на мой взгляд, замечательную технологию, как myBatis (в прошлом iBatis). Сразу скажу, что свой уровень как разработчика я не считаю высоким. И у вас я именно интересуюсь мнением, а не вступаю в спор. Но тем не менее у меня есть опыт перевода целого проекта с JPA на myBatis именно из-за читаемости, необходимости тюнинга и поддержки. Так же вы неоднократно говорили про необходимость знания SQL - т.е. мы по умолчанию считаем что человек, зовущийся Java программистом может без проблем использовать myBatis. Не кажется ли вам, что myBatis более оптимальный и читаемый вариант? Есть конечно косяки с тем что знаки больше и равно он так просто не съест, но это уже мелочи. Спасибо.
@Alellas9 жыл бұрын
+Sergey Nemchinsky ясно, учту. Спасибо!
@Чонжинди-в2о8 жыл бұрын
здраствуйте Сергей.могли-ли вы сделать коротенькое видео по алгоритмам?сортировка или что вроде этого...
@Чонжинди-в2о8 жыл бұрын
***** .Роберт Лафоре структуры данных и алгоритмы ///////// Алгоритмы на java 4-е издание Роберт Седжвик,Кевин Уэйн....пытаюсь разобраться с алгоритмами в этих книгах.только вот очень трудно по книжке учиться.да и думаю не все же алгоритмы используются.я имел в виду не могли бы вы рассказать самое нужное из этих книг??
@Чонжинди-в2о8 жыл бұрын
***** спасибо.тогда я наверное это дело отложу.
@viorelvior56869 жыл бұрын
Откуда могу взять этот код ??? Спасибо за видео урок.
@Alexander-mj3jk9 жыл бұрын
насчет 9:40 - если вылетет экзепшен, то мы пролетаем мимо finally c resultSet.close() А что насчет аннотации@Clenupиз projectlombok? Помоему удобно, даже удобней java 8, и позволяет избежать этой аццкой простыни.
@Alexander-mj3jk9 жыл бұрын
Vadya Chmil если в строках 97-98 вылетает экзепшен - мы не входим в try который в 99 строке, и поэтому пролетаем мимо блока finally строк 111-118. разве что логгер в 100 бросит экзепшен. тогда действительно то finally о котором говориться, не пролетим :)
@Alexander-mj3jk9 жыл бұрын
Vadya Chmil При чем тут я? Автор видео моделировал такую ситуацию и утверждал по запарке, что мы туда попадем.
@Dream1Lord9 жыл бұрын
Vadya Chmil "Ну а почему autoclosable не используется, то это вопрос" - Потому что Java 6
@lnnnq4 жыл бұрын
Да, разбор хороший, особенно для тех кто только начинает погружаться в яву
@СергейДедков-ц9э9 жыл бұрын
Здравствуйте, Сергей. Спасибо за видео, очень интересно, изложение радует) Есть пожелание услышать про такие паттерны, как Паттерны архитектуры источников данных Row Data Gateway (Шлюз к данным записи) Active Record (Активная запись) Table Data Gateway (Шлюз к данным таблицы) Data Mapper () Паттерны обработки Объектно-Реляционных метаданных Metadata Mapping (Распределение на основе метаданных) Query Object (Объект-запрос) Repository (Репозиторий) Паттерны логики сущности Transaction Script (Сценнарий транзакции) Domain Model (Модель области определения) Table Module (Обработчик таблицы) Service Layer (Сервисный уровень) Планируете ли вы рассказывать про это?
@nikitachizhik87867 жыл бұрын
спасибо за труд. но тут очень мелко, не видно строк и их содержимого. и может сслыка на код есть?
@аавыф-б4о3 жыл бұрын
скорей всего, у вас медленный интеренет и видео показывалось низкого разрешения. смотрел в 1080 - весь код виден настолько идеально, что скорей всего еще на 1-2 ступеньки ниже - тоже должно читаться (не пробовал).
@EdwardNorthwind Жыл бұрын
А это не слишком медленно, при таком подходе - на каждый чих подымать и вырубать конекшн? Я бы еще понял, если бы у нас был пул конекшинов, и мы из него брали уже поднятый свободный. Но вот так? Будут заметные задержки при каждом подключении. Зайдите в любой менеджер СУБД и сделайте конект, вот прикиньте почти также каждый раз.
@tzofeolam6 жыл бұрын
15:48 неверная точка зрения. Логгер никогда не напишет "и ещё столько-то строк" вместо исключения внутри исключения. Он это напишет лишь в случае слишком длинной цепочки вызовов. Вот простой код, который это демонстрирует: package org.example; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; public class MainClass { private static final Logger logger = Logger.getLogger(MainClass.class); public static void main(String[] args) { PropertyConfigurator.configure(MainClass.class.getResourceAsStream("/log4j.properties")); MainClass mc = new MainClass(); try { mc.fu(0); } catch (Exception e) { logger.error("WTF?", e); } } public void fu(int n) throws Exception { if (n > 100) { throw new Exception("Final cause exception"); } try { fu(n + 1); } catch (Exception e) { throw new Exception(e); } } } После запуска получится очень длинная цепочка из "Caused by", содержащая все без исключения места бросания исключений. Заканчиваться она будет вот так: Caused by: java.lang.Exception: java.lang.Exception: java.lang.Exception: Final cause exception at org.example.MainClass.fu(MainClass.java:29) at org.example.MainClass.fu(MainClass.java:27) ... 99 more Caused by: java.lang.Exception: java.lang.Exception: Final cause exception at org.example.MainClass.fu(MainClass.java:29) at org.example.MainClass.fu(MainClass.java:27) ... 100 more Caused by: java.lang.Exception: Final cause exception at org.example.MainClass.fu(MainClass.java:23) at org.example.MainClass.fu(MainClass.java:27) ... 101 more Process finished with exit code 0 Дело вовсе не в размере логов, а в их читаемости. Дублирующее логирование исключений приводи к тому, что такие логи труднее читать.
@salaleser7 жыл бұрын
Как обычно, все круто
@artemshpykuliak78426 жыл бұрын
Народ, может кто-то знает где можно подобные исходники взять? похожая задача, мне бы просто архитектуру глянуть и что там как с чем вяжеться. Спасибо.)
@romanreal79 жыл бұрын
а какие реалии нынче с этой темой? вот так вот на чистом JDBC никто не работает, а используют как минимум Hibernate, Spring Data, но тем не менее его знания требуют на собеседовании или как?
@asidorov018 жыл бұрын
+Sergey Nemchinsky , Это нужно объяснять студентам, потому что они так начнут кодить реальные проекты. И потом такой код только выкинуть, поскольку поддерживать такой код нереально. Ценность такого кода для клиента резко отрицательная.
@ИмяФамилия-б3л7б4 жыл бұрын
А можно тоже самое но на самом начальном уровне??? для "самых маленьких" ))))
@аавыф-б4о3 жыл бұрын
А смысл, "то же самое"? Для маленьких нужно совсем другое.
@GAVVVR9 жыл бұрын
Я правильно понял, что лучше не стоит создавать DAO интерфейсы, как в этом проекте, а лучше сразу делать DAO классы? (по крайней мере для такого игрушечного проекта). Просто в интернете я видел много примеров с интерфейсами DAO. За видео спасибо, очень познавательно, подписался.
@GAVVVR9 жыл бұрын
+Sergey Nemchinsky я сейчас делаю по сути такой же HelloWorld проект на сервлетах, только другая предметная область. И тоже думал, что в таком игрушечном проекте никак не буду зависеть от базы данных (использую H2). У меня три типа пользователей и один тип имеет отдельные поля. В Java-коде используется наследование. А в SQL я воспользовался неким шаблоном под названием TablePerType, чтобы "имитировать" наследование. И вот теперь не могу понять, как вставить одну запись в обе таблицы, потому что ID в основной таблице-предке, генерируется последовательностью, а во второй таблице этот ID должен совпадать с ID в первой для данной записи. На мой вопрос на SO (stackoverflow.com/questions/34964062/how-should-i-insert-new-data-with-tablepertype-table-structure), как быть, люди отвечают, что такое SQL выражение будет привязано к конкретной реализации РСУБД, так что, возможно, придется писать H2xxxDao классы.
@wepko2 жыл бұрын
Это был я. Ставь лайк
@HowItWorks5 жыл бұрын
Будете смеяться, но на моей практике было пару раз так, что сервер ложился из-за лог файлов и бекапов. Тупо заканчивалось свободное место. Вроде бы не много места занимает, но накапливается и совершенно внезапно выясняется что больше писать некуда.
@аавыф-б4о3 жыл бұрын
Присоединяюсь. Часто кончалось (где-то) место из-за логов. Но расследование показало, что место периодически кончалось не из-за размеров логов само по себе (ну кончалось бы оно не каждые 2 недели - а каждый месяц-полтора - но всё так же неожиданно и аварийно - если б сократили логирование в нексолько раз) - а из-за отсутствия автоматической обрезки логов (месячной давности они всёравно не нужны, допустим) и плюс что вообще никто не следил за свободным местом на сервере, т.е. никто не отвечал за это (это если более глобально).
@andrii_popov5 жыл бұрын
1) Plain JDBC - это жесть; 2) JDBC + try-catch with resources почти такая же жесть; 3) Spring JdbcTemplate - шаг к свету, 4) JPA/Hibernate - это ОК, 5)Spring Data JPA - это космос. 6) Добвьте сами в будущем...
@Alex11Fox4 жыл бұрын
JDBC +Repository
@FlawlessVictory-j8j4 жыл бұрын
@@Alex11Fox Репозиторий - это вы имеете ввиду интерфейс внутри спринга? Спринг Дату уже назвали
@Alex11Fox4 жыл бұрын
@@FlawlessVictory-j8j да, это интерфейс в спринге. Крч это Spring Data JPA. Учи JPA и будет счастье.
@svetopolk9 жыл бұрын
1. Круто, очень понравился формат 2. Зачем копировать классы с именем постгрес на имя майэскуэль... Наверное можно порефаторить и просто их переименовать? Я понимаю, это тоже не очень хорошо, но всяко лучше, чем копировать код. Кстати еще можно забить на название, будем работать с Mysql, хотя классы будут от postgre. 3. Уроки хорошие, но для краткости, я думаю можно убрать все эти "я поеду в отпуск, я организую встречу". Смотреть это будут и через год. Ты уже 100 раз вернешься из отпуска... зачем это надо?
@cgstudio20109 жыл бұрын
svetopolk У видео есть дата публикации.
@lexzcq9 жыл бұрын
svetopolk по-поводу второго вопроса - переименовывать - это тоже не комильфо, нужно писать универсальные классы, которые можно использовать как для работы с MySQL так и для работы с PostgreSQL или Oracle.
@Anton_Rozhanskii4 жыл бұрын
666 лайков, прям не хочется менять
@lEpIvIaKl2 жыл бұрын
Жесть, Сергей когда-то код писал оО
@patison88688 жыл бұрын
зашел посмотреть как организовать DAO, а тут на те, название, конекшен, эксепшены, логи, ну и в конце "не пишите интерфейсы для дао"
@maxlich91397 жыл бұрын
Я бы сказал - наезд. Про само ДАО правда было мало рассказано. Приходится смотреть в картинку, и додумывать, как там это всё устроено, и как нужно делать.
@EdwardNorthwind Жыл бұрын
Вроде что-то показал, но в том то и дело, что что-то... Да, показать типичные ошибки новичка важно, но люди тут именно для того, чтобы понять как правильно связывать слои, что и как в каждом слое делается. Хотя бы ДАО+Домен. А в итоге, вообще не понятно, что обозревали, и как оно взаимодействует.
@HowItWorks5 жыл бұрын
Так себе код. Уже очень давно так никто не делает.
@greegav7 жыл бұрын
Вот ссылка на Гитхаб с исходниками была бы бесценна. За остальное огромное спасибо.
@greegav7 жыл бұрын
Sergey Nemchinsky Перезалить на гитхаб :) тяжко перенабирать показанное, тем более глубоко не всё показано.
@eney19756 жыл бұрын
а я постоянно пишу название базы в названии классов (((
@аавыф-б4о3 жыл бұрын
Это точно неправильно, относится к архитектурным ошибкам. Вы смешиваете слой сервера приложения (где код программы и названия классов и прочие имена переменных) и сервера БД (где адрес базы, название скуля, имена таблиц). Т.о. вы нарушаете трёхзвенку. (Классическая трёхзвенная архитектура: клиент или фронт - сервер приложения - сервер БД).
тогда уж prStatement. Но всё же statement звучит лучше.
@HalfbackRUS6 жыл бұрын
нах тут вебка на 1/4 экрана и почему такой мелкий шрифт? а зачем автор напялил националистическую символику и вещает на русском языке? лол. классный канал.