-
Notifications
You must be signed in to change notification settings - Fork 35
Lesson 4
Онлайн проект Topjava
SpringMain, InMemoryAdminRestControllerTest, InMemoryAdminRestControllerSpringTestпочиним в патче 4_5_create_inmemory_test_ctx.patch (видео 4)
- В
JdbcUserRepositoryImplпоменялMapSqlParameterSourceнаBeanPropertySqlParameterSource(поля для вставки определяются через отражение в бине и метаданные в SQL запросе). ВJdbcMealRepositoryImplостаетсяMapSqlParameterSource, т.к. в отсутствуетMeal.userId. См. дополнительно CombinedSqlParameterSource- Новый Postgres драйвер поддерживает Java 8 Date and Time. Преобразования c
Timestampуже не нужны.- В meals добавил составной индекс
INDEX meals_unique_user_datetime_idx ON meals(user_id, date_time)для повышения скорости запросов по этим полям
Примечание: в ответе на Why is SELECT * considered harmful? есть случаи, когда она допустима (наш случай):
When "*" means "a row"
- POSTGRESQL: BETWEEN CONDITION
-
Сравнение времени выполнения для разных индексов
- На id как на primary key индекс создается автоматически.
- все запросы в таблицу meals у нас идут с
user_id - по полю
date_timeтакже есть запросы + мы по нему сортируем список результатов, те они- хорошие кандидаты для индексирования. - следует иметь в виду, индексы ускоряют операции чтения, но замедляют вставку и удаление, поэтому необходим анализ в реальном приложении
- Оптимизация запросов. Основы EXPLAIN в PostgreSQL
- Оптимизация запросов. Часть 2
- Оптимизация запросов. Часть 3
- Документация Postgres: индексы
Удалил лишние
MealsUtil.MEALS
- Сделайте интеграцию своего GitHub репозитория и подключите сверху своего README.md (Raw) интергацию с
-
Codacy Check code (проверка стиля и поиск багов в коде). В Codacy Issues
- отключил в настройках (remove pattern) проверку assert в JUnit (проверяем через матчеры) и
meta http-equiv="content-type"в JSP - сделал remove pattern на Cross Site Scripting (XSS), будем делать защиту на последнем занятии
- отключил в настройках (remove pattern) проверку assert в JUnit (проверяем через матчеры) и
- Сборку и тесты Travis (результат выполнения тестов проекта)
- Сервис по проверке
mavenзависимостей VersionEye закрыли. Ищу замену...
-
Codacy Check code (проверка стиля и поиск багов в коде). В Codacy Issues
- Сделайте
pushдля отображения результатов текущего состояния проекта.
Для пояснения материала видео следал проверку предусловий Objects.requireNonNull и Assert.notNull. В реальном проекте везде используются один подход.
- Перенес проверки предусловий
AssertизInMemoryрепозиториев в сервисы- Добавил конфигурацию
.travis.yml- Сделал класс
Utilс новым методомorElse(MealRestController.getBetween() has an NPath complexity of 625)
- Цикломатическая_сложность (NPath complexity): количество линейно независимых маршрутов через программный код.
- Контрактное программирование, Программирование по контракту
- Comparison Preconditions in Java
- IDEA Settings -> Plugins -> Browse repositories... Add QAPlug: PMD/FindBugs/Checkstyle/Hammurapi
- Tools -> QAPlug -> Analyze Code...
- IDEA Analyze | Inspect Code
Переименовал
mock.xmlвinmemory.xml
Entity- класс (объект Java), который в ORM маппится в таблицу DB.
- ВНИМАНИЕ: патч меняет
postgres.properties, в котором у вас возможно свои креденшелы к базе.hibernate-core5.2.x включаетhibernate-entitymanagerиhibernate-java8, Time API конверторы уже не нужны.- EL implementation provided by the container. In a Java SE you have to add an implementation as dependency to your POM file: добавил
javax.elзависимость соscope=provided
- Внимание: при настройке JPA в IDEA НЕ скачивайте библиотеку javaee.jar (и любую другую). Все зависимости в проект попадают только через Maven.
- Тесты и приложение ломаются.
MealServiceTestпочинится после выполнения HW04 (JpaMealRepositoryImpl)- Если вы используете Java 9, то возникают проблемы с
JAXBException(пакетjava.xml.bind). См. решение
- Дополнительно:
- ORM.
- JPA и Hibernate в вопросах и ответах
- Наследование в Hibernate: выбор стратегии
- JPA EntityManager: управляем сущностями
- Field vs property access
- Hibernate: введение и написания Hello world приложения
- 15 reasons why we need to choose Hibernate over JDBC
- Mapping: описания модели Hibernate (hbm.xml/annotation).
- Hibernate. Другие ORM: TopLink, EсlipseLink, EBean (used in Playframework).
- JPA (wiki). JPA (english wiki). JPA Performance Benchmark
- Стратегии генерации PK
- hibernate-validator. JSR-303 -> JSR-349
- Описание связей в модели. Ленивая загрузка объекта.
- JPA definitions
- Spring expressions: выражения в конфигурации
- HQL/ JPQL.
- Динамические запросы (которые формируются в коде): JPA Criteria API. Unified Queries for Java
- Using the Java 8 Date Time Classes with JPA
- Транзакция. ACID. Уровни изоляции транзакций.
- Spring Transaction Management
- readOnly и Propagation.SUPPORTS
@Transactionalв тестах. Настройка EntityManagerFactory
Справочник:
- Видео: Вячеслав Круглов — Как начинающему Java-разработчику подружиться со своей базой данных?
- Видео: Николай Алименков — Босиком по граблям Hibernate
- Стратегии работы с транзакциями
- Примеры работы с JPA
- Spring transaction propagation tutorial
- Getting Started with JPA
- Java Persistence
- Разделы по Java Persistence API
- Spring Framework transaction management
- Spring Persistence Tutorial
- Working with JPA Entity Objects
- Стратегии работы с транзакциями: Распространенные ошибки
- Принципы работы СУБД. MVCC
- MVCC
- ВНИМАНИЕ: патч меняет
postgres.properties- IDEA может
${jdbc.initLocation}подчеркивать красным - тупит...
Есть несколько аналогичных "встроенных" баз данных. H2, HSQLDB, Derby, SQLite. Почему был выбран HSQLDB?
Просто с ней приходилось работать. HSQLDB и H2 наиболее популярны, в новом курсе по spring-boot планирую использовать H2. Здесь интересное краткое описание встраиваемых баз данных в Java. В HSQLDB нет репликаций, кластеризации и объем данным ограничен несколькими TB. Для большого количества приложений она подходит и для продакшена. См.
Чистого JPA не существует, т.е. это всего лишь интерфейс, спецификация? Говорим JPA, подразумеваем какой-то ORM фрэймворк? А что тогда используют чистый jdbc, Spring-jdbc, MyBatis? MyBatis не реализует JPA?
ORM это технология связывания БД и объектов приложения, а JPA - это JavaEE спецификация (API) этой технологии. Реализации JPA - Hibernate, OpenJPA, EclipceLink, но, например, Hibernate может работать по собственному API (без JPA, которая появиласть позже). Spring-JDBC, MyBatis, JDBI не реализуют JPA, это обертки к JDBC. Все ORM и JPA также реализованы поверх JDBC.
В зависимостях maven
hibernate-entitymanagerтянет за собойjboss-logging. Как будет происходить логгирование?
How do you configure logging in Hibernate 4 to use SLF4J: в нашем проекте автоматически подхватывается logback-classic.
В чем преимущество Hibernate ?
Hibernate (как любая ORM) реализует маппинг таблиц в объекты Java. Когда мы добавим роли к пользователю вы увидете, насколько код будет проще, чем в jdbc. Также см. 5 Reasons to Use JPA / Hibernate
Чем отличается
@Column(nullable = false)от@NotNullи есть ли необходимость указывать обе аннотации ?
@Column(nullable = false) это атрибуты колонки таблицы базы. @NotNull - это валидация, которая происходит в приложении перед вставкой в базу. Если колонка ненулевая, то NOT NULL объязательна. Валидация- опциональна. Также см.
@NotNull vs @Column(nullable = false)
почему мы в в бине
entityManagerFactoryне указали диалект базы данных?
Он автоматически определяется из DataSource драйвера
В чем разница между
persistиmerge
Подробный ответ со Stackovwrflow с объяснением разницы. Упрощенно:
-
merge, в отличие отpersist, если entity нет в текущей сессии, делает запрос в базу данных - entity, переданный в
mergeне меняется. Нужно использовать возвращаемый результат
em.merge- при отсутствии старой записи (несуществующееid) создает новую. Те вJpaUserRepositoryImplнарушается логика
В Hibernate есть такая бага: https://hibernate.atlassian.net/browse/HHH-1661
- Hibernate unexpectedly issues INSERT instead of throwing the javax.persistence.OptimisticLockException, when a nonexistent entity is passed to merge()
- Should Hibernate Session#merge do an insert when receiving an entity with an ID?
Если это действительно наш критичный бизнес кейс (например с многопоточным удалением entity) нужно искать варианты обходного решения. Если же это результат неверного запроса, то, мое мнение, можно это оставить как есть.
Почему в проекте транзакционность сделана в слое репозитория, а не сервиса? Транзакциями удобнее пользоваться на слое сервисов, так как здесь реализуется бизнес логика и бывает нужно делать несколько операций в одной транзакции.
С классической точки зрения все транзакции действительно объявляются на уровне сервиса. Мы будем использовать в логике сервиса несколько запросов и тогда сделаем дополнительную транзакцию на методе сервисе. Новая транзакция при этом не создается (по умолчанию используется Propagation.REQUIRED, который поддерживают существующую), поэтому несколько @Transactional аннотаций ведут себя как одна. Я использую подход spring-data-jpa (будет на следующем занятии): в репозитории транзакции объявлять удобно, тк не надо думать о них в сервисах.
- 1: Сделать из
MealHibernate entity - 2: Имплементировать и протестировать
JpaMealRepositoryImpl
- 3: Добавить в тесты
MealServiceTestфункциональность@Rule:- 3.1: проверку Exception
- 3.2: вывод в лог времени выполнения каждого теста
- 3.3: вывод сводки в конце класса: имя теста - время выполнения
- JUnit @Rules
- замена ExpectedException
-
1: Тк. JPQL работает с объектами мы не можем использовать
userIdдля сохранения. Можно сделать например так:User ref = em.getReference(User.class, userId); meal.setUser(ref);При этом от
Userнам нужет толькоid. Создается lazy прокси надid, которая обращается к базе при запросе любого поля. Т.е. у нас запроса в базу за юзером не будет- проверьте по логам Hibernate
Внимание: проверять запросы Hibernate нужно через run. Если делаете debug и брекпойнт, то могут делаться лишние запросы к базе (дебаггер дергает toString)
- 2: В JPQL запросах можно писать:
m.user.id=:userId - 3: При реализации
JpaMealRepositoryImplпредпочтительно не использоватьtry-catchв логике реализации. Но если очень хочется, то ловить только специфичекские эксепшены (пр.NoResultException), чтобы, например, при отсутствии коннекта к базе приложение отвечало адекватно. - 4: Мы будем смотреть генерацию db скриптов из модели, для корректной генерации нужно в
MealдобавитьuniqueConstraints - 5: При записи в базу через
namedQueryвалидация ентити не работает, только валидация в бд - 6: Результат
AssertionErrorпечатает результаты черезtoString, который может не совпадать с полями сравнения. - 7: Если нашему приложению
Meal.userне требуется, не следует включать его в тесты. В следующем уроке мы потренируемся разными способами доставать зависимостиMeal.userиUser.meals - 8: Старые версии IDEA тупят по поводу проверки
BETWEEN. Обновитесь либо не обращайте внимания.
Новая информация плохо оседает в голове, когда дается в виде патчей, поэтому, чтобы она стала "твоей" нужно еще раз проделать это самостоятельно. Домашнее задание на этом уроке небольшое, а полученных знаний уже достаточно, чтобы после его выполнения начинать делать выпускной проект, сделанный на нашем стеке.
- Для проекта я взял реальное тестовое задание, поэтому жалоб не неясность формулировок принимать не буду- сделайте как поняли. Представьте, что это ваше тестовое задание на работу.
- Общение в канале Slack #graduation
- Ревью проекта входит в участие с проверкой домашних заданий (ревьюится один раз!). Отдать на ревью нужно до 09.01.2019 (если идешь на проект "Многомодульный maven. Многопоточность. XML (JAXB/StAX). Веб сервисы (JAX-RS/SOAP). Удаленное взаимодействие (JMS/AKKA) (Masterjava)", то срок до 31.03.2019).
- По завершению ты сможешь занести этот проект в свое портфолио и резюме как собственный, без всяких оговорок.
- Обязательно проверяйся по рекомендациям в конце выпускного
Разбор домашнего задания HW3
1.
Ваши вопросы
Подсказки по HW4