diff --git a/generate-entities-from-db/text-based-guide/generate-entities-from-db.md b/generate-entities-from-db/text-based-guide/generate-entities-from-db.md new file mode 100644 index 0000000..1f76072 --- /dev/null +++ b/generate-entities-from-db/text-based-guide/generate-entities-from-db.md @@ -0,0 +1,448 @@ +# Создание Spring Data JPA (Hibernate) сущностей из БД (PostgreSQL, MySQL, Oracle) + +[![Смотреть на Youtube](images/youtube-thumbnail.png)](https://www.youtube.com/watch?v=uxdec6WIWEg) + +**Примерное время прочтения: 15 минут.** + +Если вы предпочитаете сначала разработать схему базы данных, а затем реализовать JPA модель, или вам необходимо создать приложение поверх уже существующей базы данных, тогда Amplicode станет для вас чрезвычайно удобным инструментом, который сэкономит много времени и избавит от рутинной работы. + +Используя действие **JPA Entities from DB**, вы можете преобразовать таблицы базы данных в JPA сущности всего в несколько кликов, учитывая особенности структуры таблиц, такие как ограничения, индексы, свойства столбцов и т.д. Amplicode настолько глубоко понимает вашу модель, что может в подавляющем большинстве случаев правильно определить кардинальность, будь то один к одному, один ко многим, многие к одному или даже многие ко многим. Самое потрясающее в этом всем то, что нам не надо пересоздавать всю сущность, если что-то изменится в схеме базы данных. Вместо этого Amplicode сможет обнаружить, что именно изменилось, и внесет изменения, которые не затронут существующий код. + +Давайте посмотрим на все это в действии. + +## Задачи на сегодня + +Сегодня мы будем заниматься разработкой приложения для небольшого блога. В нашей базе данных мы будем хранить пользователей, их посты, комментарии и отображать статистику: количество постов, созданных каждым пользователем. + +![blog-application-data-model.png](images/blog-application-data-model.png) + +Шаги, которые необходимо выполнить в рамках решения поставленной задачи, следующие: + +* Инициализация схемы БД +* Создание Spring Boot приложения +* Настройка подключения к БД +* Создание JPA сущностей из таблиц базы данных +* Модификация JPA модели и создание `@MappedSuperclass` +* Cherry-pick изменений из БД в JPA модель +* Создание JPA сущности для DB View + +## Инициализация схемы БД + +Для первой версии приложения понадобится создать две таблицы: `users` и `posts`. Для этого вам следует выполнить следующие скрипты через pgAdmin. + +```sql +CREATE TABLE users +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + created_by VARCHAR(255), + created_date TIMESTAMP WITHOUT TIME ZONE, + last_modified_by VARCHAR(255), + last_modified_date TIMESTAMP WITHOUT TIME ZONE, + first_name VARCHAR(255), + last_name VARCHAR(255), + CONSTRAINT pk_users PRIMARY KEY (id) +); + +CREATE TABLE posts +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + created_by VARCHAR(255), + created_date TIMESTAMP WITHOUT TIME ZONE, + last_modified_by VARCHAR(255), + last_modified_date TIMESTAMP WITHOUT TIME ZONE, + title VARCHAR(255), + test OID, + publiched_at TIMESTAMP WITHOUT TIME ZONE, + author_id BIGINT NOT NULL, + CONSTRAINT pk_posts PRIMARY KEY (id) +); +``` + +Для улучшения производительности запросов к таблице `users` создайте составной индекс для столбцов имени и фамилии. + +```sql +CREATE INDEX idx_user_names ON "users" (first_name, last_name); +``` + +Один пользователь может создать несколько постов, поэтому кардинальность отношения будет типа "многие к одному", реализованная через внешний ключ в таблице `posts`. Для ее реализации выполните следующий запрос: + +```sql +ALTER TABLE posts + ADD CONSTRAINT FK_POSTS_ON_AUTHOR FOREIGN KEY (author_id) REFERENCES users (id); +``` + +После выполнения всех скриптов проверьте актуальное состояние базы данных через pgAdmin, и далее можно будет приступать к разработке собственно Spring Boot приложения. + +![database-in-pg-admin.png](images/database-in-pg-admin.png) + +## Создание Spring Boot приложения + +Чтобы сгенерировать Spring Boot приложение, воспользуйтесь [Spring Initializr](https://start.spring.io). + +![spring-init.png](images/spring-init.png) + +На странице генерации приложения: + +* Установите название группы и артефакты (1) + +* Нажмите на ADD DEPENDENCIES (2) + +* Добавьте зависимости для Spring Data JPA и PostgreSQL (3) + +* Все остальные настройки оставьте по умолчанию + +* Нажмите **GENERATE** (4) + +![generate.png](images/generate.png) + +Теперь откройте сгенерированное приложение в IntelliJ IDEA. + +## Настройка подключения к БД + +Теперь надо настроить источник данных для корректной работы со Spring Data JPA. + +С Amplicode настроить источник данных довольно легко: + +* Нажмите правой кнопкой мыши по узлу **Data Sources** +* Выберите опцию **New** -> **Default Data Source** + +![create-jpa-datasource-option.png](images/create-jpa-datasource-option.png) + +* В открывшемся окне выберите тип базы данных (PostgreSQL) (1) + +* Укажите необходимые параметры для подключения к источнику данных (2) + +* Благодаря действию **Test Connection** можно убедиться в корректности указанных параметров для источника данных (3) + +* Кроме того, имеет смысл сразу же создать подключение к базе данных: для этого отметим чекбокс **Create DB Connection**. (4) + +![create-db-connection.png](images/create-db-connection.png) + +> Подключение к базе данных необходимо для дальнейшей корректной работы таких возможностей Amplicode как создание сущности на основе таблиц в базе данных, а также генерация скриптов миграции. + +* В диалоге создания подключения оставьте те же значения, которые мы указали для источника данных. + +![db-connection-parameter-values.png](images/db-connection-parameter-values.png) + +* Нажмите **OK** + +Все необходимые параметры для источника данных будут сгенерированы в `application.properties`: + +```properties +#Datasource configuration +spring.datasource.url=jdbc:postgresql://localhost/blog +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=org.postgresql.Driver +``` + +Также будет создано подключение к нашей базе данных. + +Теперь можно приступать к следующему шагу - разработке JPA модели. + +## Создание JPA сущностей из таблиц базы данных + +С помощью Amplicode легко справиться с задачей создания JPA модели, отталкиваясь от существующей базы данных. Для этого: + +* В дереве проекта нажмите правую кнопку мыши на имени корневого пакета + +![root-package-name.png](images/root-package-name.png) + +* В появившемся всплывающем меню выберите действие **New** -> **JPA Entities from DB** + +![jpa-entities-from-db-action.png](images/jpa-entities-from-db-action.png) + +* В открывшемся окне выберите таблицу `posts` + +![select-table-posts.png](images/select-table-posts.png) + +Amplicode проанализирует структуру таблицы и предложит типы атрибутов сущности, отталкиваясь от типов столбцов таблицы. + +![entity-attribute-types-suggested.png](images/entity-attribute-types-suggested.png) + +Amplicode прекрасно понимает, что некоторым типам данных в базе данных может соответствовать несколько Java классов, и выбор того или иного типа может отличаться от приложения к приложению. Поэтому Amplicode не ограничивает нас строгим соответствием, а позволяет выбрать один из доступных вариантов там, где это возможно. + +![select-one-of-possible-types.png](images/select-one-of-possible-types.png) + +* Для первичного ключа на уровне JPA используйте стратегию **IDENTITY**. + +![identity-strategy.png](images/identity-strategy.png) + +* Выберите столбец, представляющий собой внешний ключ на таблицу `users`. + +![external-key.png](images/external-key.png) + +> Amplicode знает, что для реализации ассоциативного атрибута на уровне JPA нам понадобится сущность `User`. Поэтому он автоматически выбирает связанную таблицу. Кроме того, Amplicode позволяет нам создать ассоциативный атрибут "один ко многим" от пользователей к их постам. Подобная связь не может существовать на уровне реляционной базы данных, однако является довольно удобной для JPA модели. + +![one-to-many.png](images/one-to-many.png) + +Таким образом, в сущности `User` мы можем хранить коллекцию постов, связанных с каждым пользователем. + +```java + @OneToMany(mappedBy = "author") + private Set posts = new LinkedHashSet<>(); +``` + +Стоит отметить, что несмотря на то, что наши таблицы называются во множественном числе (`users`, `posts`), что является довольно распространенным подходом к именованию таблиц на уровне базы данных, на уровне JPA модели принято придерживаться именования в единственном числе (`User`). + +Amplicode автоматически установил названия для сущностей в единственном числе. + +![plural-vs-singular.png](images/plural-vs-singular.png) + +Кроме того, в случае необходимости всегда можно изменить эти значения или даже более тонко настроить механизм именования в настройках, сконфигурировав значения полей с префиксами и постфиксами, которые можно будет пропустить при генерации названия сущности или даже через Java код без каких-либо ограничений. + +![prefixes-and-postfixes-config.png](images/prefixes-and-postfixes-config.png) + +Для этого достаточно воспользоваться ссылкой **Other Settings** и выбрать опцию **Reverse Engineering**. + +![reverse-engineering.png](images/reverse-engineering.png) + +Как вы помните, у нас также есть индекс для таблицы `users` в базе данных. Amplicode также может реализовать его на уровне JPA модели. Для миграции существующих индексов и ограничений достаточно выбрать соответствующий чекбокс. + +![migrate-indexes-and-constraints.png](images/migrate-indexes-and-constraints.png) + +Последним шагом определите отдельный пакет для сущностей, введя его название в поле **Package**. + +![package-for-entities.png](images/package-for-entities.png) + +Заполнение формы на этом завершено и теперь необходимо просто нажать **OK**. + +Все сущности будут сгенерированы Amplicode вместе с базовыми и ассоциативными атрибутами, а также индексом. + +![generation-result.png](images/generation-result.png) + +Можно переходить к следующему шагу. + +## Модификация JPA модели: создание @MappedSuperclass + +Прекрасно понимая, что наше приложение со временем будет разрастаться, можно уже сейчас улучшить нашу JPA модель и подготовиться к расширению заранее. Например, идентификатор, а также все поля, связанные с аудитом, например, дата создания и последнего изменения, а также имя пользователя, выполнявшего это самое создание и изменение, будут нужны для подавляющего большинства сущностей. + +![common-attributes.png](images/common-attributes.png) + +Для решения подобной задачи принято использовать `@MappedSuperclass`, от которого будут унаследованы все остальные сущности. Amplicode позволяет осуществить необходимый рефакторинг предельно удобным образом. + +Прежде всего, воспользуйтесь стандартной комбинацией клавиш для вызова контекстного меню IntelliJ IDEA: **Alt+Enter** для Windows/Linux или **⌥+Enter** для macOS. Далее: + +* Выберите опцию **Extract to MappedSuperClass** + +![extract-to-mappedsuperclass-in-menu.png](images/extract-to-mappedsuperclass-in-menu.png) + +* В появившемся диалоге создания `@MappedSuperclass` зададйте название класса и отметьте все атрибуты, которые нужно вынести в родительский класс + +![superclass-name-and-attributes.png](images/superclass-name-and-attributes.png) + +* Нажмите **OK** + +`@MappedSuperclass` готов. + +```java +@MappedSuperclass +public class BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + private Long id; + + @Column(name = "created_by") + private String createdBy; + + @Column(name = "created_date") + private Instant createdDate; + + @Column(name = "last_modified_by") + private String lastModifiedBy; + + @Column(name = "last_modified_date") + private Instant lastModifiedDate; + + //Геттеры и сеттеры опущены для краткости +} +``` + +Теперь примените аналогичные изменения и к сущности `User`, отредактировав код вручную. Код класса должен приобрести следующий вид: + +```java +@Entity +@Table(name = "users", indexes = { + @Index(name = "idx_user_names", columnList = "first_name, last_name") +}) +public class User extends BaseEntity { + @Column(name = "first_name", nullable = false) + private String firstName; + + @Column(name = "last_name", nullable = false) + private String lastName; + + @OneToMany(mappedBy = "author") + private Set posts = new LinkedHashSet<>(); + + //Геттеры и сеттеры опущены для краткости + +} +``` + + +## Cherry-pick изменений из БД в JPA модель + +Учесть все нюансы, разрабатывая приложение с нуля, довольно сложно. Вот и мы забыли добавить данные об электронной почте пользователя и времени его последней активности. + +![forgotten-attributes.png](images/forgotten-attributes.png) + +Кроме того, мы хотели хранить информацию о комментариях пользователей к постам. + +В соответствии с подходом к разработке "от базы данных", прежде всего добавьте необходимые поля в таблицу `users` и создайте новую таблицу `comments` вместе со связующей таблицей `comments_posts`. + +![changes-to-the-data-model.png](images/changes-to-the-data-model.png) + +Для этого необходимо выполнить следующие SQL запросы: + +```sql +ALTER TABLE users + ADD email VARCHAR(255); + +ALTER TABLE users + ADD last_activity TIMESTAMP WITHOUT TIME ZONE; + + +CREATE TABLE comments +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + created_by VARCHAR(255), + created_date TIMESTAMP WITHOUT TIME ZONE, + last_modified_by VARCHAR(255), + last_modified_date TIMESTAMP WITHOUT TIME ZONE, + author_id BIGINT, + text VARCHAR(255), + CONSTRAINT pk_comments PRIMARY KEY (id) +); + +CREATE TABLE comments_posts +( + comments_id BIGINT NOT NULL, + posts_id BIGINT NOT NULL, + CONSTRAINT pk_comments_posts PRIMARY KEY (comments_id, posts_id) +); + +ALTER TABLE comments + ADD CONSTRAINT FK_COMMENT_ON_AUTHOR FOREIGN KEY (author_id) REFERENCES users (id); + +ALTER TABLE comments_posts + ADD CONSTRAINT fk_compos_on_comments FOREIGN KEY (comments_id) REFERENCES comments (id); + +ALTER TABLE comments_posts +ADD CONSTRAINT fk_compos_on_posts FOREIGN KEY (posts_id) REFERENCES posts (id); +``` + +С Amplicode можно догенерировать недостающие атрибуты в JPA модель, не потеряв при этом уже реализованных изменений. + +Можно воспользоваться панелью Generate от IntelliJ IDEA. Для ее вызова следует нажать **Alt+Insert** для Widows/Linux или **⌘+N** для macOS. + +![generate-panel-intellij-idea.png](images/generate-panel-intellij-idea.png) + +В рамках этой панели для внесения изменений в модель Amplicode предоставляет действие **Entity Attributes from DB**. + +Однако, достичь того же самого результата можно и через уже известное нам диалоговое окно **JPA Entities from DB**, вызываемое из меню **New**, которое появляется при нажатии правой клавиши мыши на дереве проекта. + +![menu-new-from-project-tree.png](images/menu-new-from-project-tree.png) + +Диалоговое окно **JPA Entities from DB** предоставляет список таблиц, для которых уже есть сущности в проекте. + +![list-of-tables.png](images/list-of-tables.png) + +Найдите нужную таблицу (`users`) и выберите новые поля, которые надо создать. + +![select-new-fields-in-table.png](images/select-new-fields-in-table.png) + +Перейдите к новой таблице `comments`. Для нее мы можем сразу указать родительскую сущность `BaseEntity`. Amplicode отметит те атрибуты, которые будут унаследованы от базового класса. + +![comments-with-base-entity.png](images/comments-with-base-entity.png) + +Также он корректно определит связь "многие ко многим" между постами и комментариями. + +![many-to-many-detected.png](images/many-to-many-detected.png) + +Отметьте чекбокс **to posts via join table com posts**. + +![to-posts-checkbox-checked.png](images/to-posts-checkbox-checked.png) + +Нажмите **OK**. Новая сущность и связь "многие ко многим" будут реализованы. + +![many-to-many-implemented.png](images/many-to-many-implemented.png) + +Кроме того, новые атрибуты будут добавлены в уже существующую сущность `User` без изменения ранее написанного кода. + +![new-attributes-old-entity.png](images/new-attributes-old-entity.png) + +## Создание JPA сущности для DB View + +Последнее, что нам осталось сделать сегодня - реализовать агрегацию статистики пользователей. Для этого необходимо создать представление на уровне базы данных, а на уровне JPA модели можно поступить с представлением точно так же, как и до этого с таблицей, что есть создать для него JPA сущность. + +Для создания представления в базе данных выполните следующие SQL запросы: + +```sql +CREATE VIEW user_statistics(user_id, number_of_posts) AS +SELECT u.id AS user_id, + count(p.id) AS number_of_posts +FROM users u + JOIN posts p ON u.id = p.author_id +GROUP BY u.id; +``` + +Воспользуйтесь уже знакомым нам диалогом по созданию сущности на основе базы данных и выберите новое представление. + +![select-view-from-db.png](images/select-view-from-db.png) + +У представлений в базе данных нет первичных ключей, но у сущности JPA должен быть идентификатор. Поэтому нам нужно выбрать поле или набор полей, которые могут выступать в качестве идентификатора сущности. Для этого нажмите на ссылку **Select columns to be used as primary key**. + +Появится всплывающее окно, позволяющее выбрать одно или несколько полей для этой цели. Выберите идентификатор пользователя, так как в данном случае он выглядит как самый подходящий вариант. + +![select-primary-key-columns.png](images/select-primary-key-columns.png) + +Нажмите **OK** сначала в маленьком окошке, а затем и большом диалоговом окне. + +Сущность готова. Так как сохранять данные в представлении напрямую нельзя, необходимо отметить нашу сущность аннотацией `@Immutable`. Amplicode также знает про это и сам добавит необходимую аннотацию. Кроме того, для гарантии невозможности создания новых экземпляров этой сущности Amplicode сгенерирует конструктор без параметров с модификатором `protected`. + +Наконец, для всех полей будут сгенерированы только геттеры, чтобы не дать разработчикам возможность изменять значения атрибутов. В целом, сущность представления будет сгенерирована в соответствии со всеми Best Practices. Amplicode заботится о качестве кода за нас: + +```java +/** + * Mapping for DB view + */ +@Entity +@Immutable +@Table(name = "user_statistics") +public class UserStatistic { + @Id + @Column(name = "user_id") + private Long userId; + + @Column(name = "number_of_posts") + private Long numberOfPosts; + + public Long getUserId() { + return userId; + } + + public Long getNumberOfPosts() { + return numberOfPosts; + } + + protected UserStatistic() { + } +} +``` + +## Заключение + +Подводя итог, все поставленные в данном гайде задачи успешно выполнены примерно за 15 минут. Вы увидели, как Amplicode помогает во время разработки приложения с уже существующей базой данных. + +Вы научились: +1. Инициализировать схему БД +2. Настраивать подключения к БД +3. Создавать JPA сущности из таблиц базы данных +4. Модифицировать JPA модель и создавать `@MappedSuperclass` +5. Осуществлять cherry-pick изменений из БД в JPA модель +6. Создавать JPA сущность для DB View + +Мы очень надеемся, что эти возможности сделают вашу работу еще более легкой и приятной. Спасибо за прочтение гайда, и подписывайтесь на наш [Telegram канал](https://t.me/+8RZ1V1mxrHw0MmQy), чтобы узнать еще больше о возможностях Amplicode. + diff --git a/generate-entities-from-db/text-based-guide/images/blog-application-data-model.png b/generate-entities-from-db/text-based-guide/images/blog-application-data-model.png new file mode 100644 index 0000000..b7d04cd Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/blog-application-data-model.png differ diff --git a/generate-entities-from-db/text-based-guide/images/changes-to-the-data-model.png b/generate-entities-from-db/text-based-guide/images/changes-to-the-data-model.png new file mode 100644 index 0000000..9201efa Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/changes-to-the-data-model.png differ diff --git a/generate-entities-from-db/text-based-guide/images/comments-with-base-entity.png b/generate-entities-from-db/text-based-guide/images/comments-with-base-entity.png new file mode 100644 index 0000000..c005f15 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/comments-with-base-entity.png differ diff --git a/generate-entities-from-db/text-based-guide/images/common-attributes.png b/generate-entities-from-db/text-based-guide/images/common-attributes.png new file mode 100644 index 0000000..95435f7 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/common-attributes.png differ diff --git a/generate-entities-from-db/text-based-guide/images/create-db-connection.png b/generate-entities-from-db/text-based-guide/images/create-db-connection.png new file mode 100644 index 0000000..f8cd133 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/create-db-connection.png differ diff --git a/generate-entities-from-db/text-based-guide/images/create-jpa-datasource-option.png b/generate-entities-from-db/text-based-guide/images/create-jpa-datasource-option.png new file mode 100644 index 0000000..b37c067 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/create-jpa-datasource-option.png differ diff --git a/generate-entities-from-db/text-based-guide/images/database-in-pg-admin.png b/generate-entities-from-db/text-based-guide/images/database-in-pg-admin.png new file mode 100644 index 0000000..660327b Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/database-in-pg-admin.png differ diff --git a/generate-entities-from-db/text-based-guide/images/db-connection-parameter-values.png b/generate-entities-from-db/text-based-guide/images/db-connection-parameter-values.png new file mode 100644 index 0000000..b3adb3b Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/db-connection-parameter-values.png differ diff --git a/generate-entities-from-db/text-based-guide/images/entity-attribute-types-suggested.png b/generate-entities-from-db/text-based-guide/images/entity-attribute-types-suggested.png new file mode 100644 index 0000000..045ab32 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/entity-attribute-types-suggested.png differ diff --git a/generate-entities-from-db/text-based-guide/images/external-key.png b/generate-entities-from-db/text-based-guide/images/external-key.png new file mode 100644 index 0000000..118f584 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/external-key.png differ diff --git a/generate-entities-from-db/text-based-guide/images/extract-to-mappedsuperclass-in-menu.png b/generate-entities-from-db/text-based-guide/images/extract-to-mappedsuperclass-in-menu.png new file mode 100644 index 0000000..c0c19cd Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/extract-to-mappedsuperclass-in-menu.png differ diff --git a/generate-entities-from-db/text-based-guide/images/forgotten-attributes.png b/generate-entities-from-db/text-based-guide/images/forgotten-attributes.png new file mode 100644 index 0000000..3c02fbe Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/forgotten-attributes.png differ diff --git a/generate-entities-from-db/text-based-guide/images/generate-panel-intellij-idea.png b/generate-entities-from-db/text-based-guide/images/generate-panel-intellij-idea.png new file mode 100644 index 0000000..e7931d3 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/generate-panel-intellij-idea.png differ diff --git a/generate-entities-from-db/text-based-guide/images/generate.png b/generate-entities-from-db/text-based-guide/images/generate.png new file mode 100644 index 0000000..48c05fd Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/generate.png differ diff --git a/generate-entities-from-db/text-based-guide/images/generation-result.png b/generate-entities-from-db/text-based-guide/images/generation-result.png new file mode 100644 index 0000000..c5222c5 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/generation-result.png differ diff --git a/generate-entities-from-db/text-based-guide/images/identity-strategy.png b/generate-entities-from-db/text-based-guide/images/identity-strategy.png new file mode 100644 index 0000000..ae38984 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/identity-strategy.png differ diff --git a/generate-entities-from-db/text-based-guide/images/jpa-entities-from-db-action.png b/generate-entities-from-db/text-based-guide/images/jpa-entities-from-db-action.png new file mode 100644 index 0000000..54869fa Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/jpa-entities-from-db-action.png differ diff --git a/generate-entities-from-db/text-based-guide/images/list-of-tables.png b/generate-entities-from-db/text-based-guide/images/list-of-tables.png new file mode 100644 index 0000000..377deae Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/list-of-tables.png differ diff --git a/generate-entities-from-db/text-based-guide/images/many-to-many-detected.png b/generate-entities-from-db/text-based-guide/images/many-to-many-detected.png new file mode 100644 index 0000000..833c29d Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/many-to-many-detected.png differ diff --git a/generate-entities-from-db/text-based-guide/images/many-to-many-implemented.png b/generate-entities-from-db/text-based-guide/images/many-to-many-implemented.png new file mode 100644 index 0000000..b511e7e Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/many-to-many-implemented.png differ diff --git a/generate-entities-from-db/text-based-guide/images/menu-new-from-project-tree.png b/generate-entities-from-db/text-based-guide/images/menu-new-from-project-tree.png new file mode 100644 index 0000000..7cb500c Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/menu-new-from-project-tree.png differ diff --git a/generate-entities-from-db/text-based-guide/images/migrate-indexes-and-constraints.png b/generate-entities-from-db/text-based-guide/images/migrate-indexes-and-constraints.png new file mode 100644 index 0000000..8ae39ac Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/migrate-indexes-and-constraints.png differ diff --git a/generate-entities-from-db/text-based-guide/images/new-attributes-old-entity.png b/generate-entities-from-db/text-based-guide/images/new-attributes-old-entity.png new file mode 100644 index 0000000..163c922 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/new-attributes-old-entity.png differ diff --git a/generate-entities-from-db/text-based-guide/images/one-to-many.png b/generate-entities-from-db/text-based-guide/images/one-to-many.png new file mode 100644 index 0000000..b9d9203 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/one-to-many.png differ diff --git a/generate-entities-from-db/text-based-guide/images/package-for-entities.png b/generate-entities-from-db/text-based-guide/images/package-for-entities.png new file mode 100644 index 0000000..9b84bb5 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/package-for-entities.png differ diff --git a/generate-entities-from-db/text-based-guide/images/plural-vs-singular.png b/generate-entities-from-db/text-based-guide/images/plural-vs-singular.png new file mode 100644 index 0000000..819fdfb Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/plural-vs-singular.png differ diff --git a/generate-entities-from-db/text-based-guide/images/prefixes-and-postfixes-config.png b/generate-entities-from-db/text-based-guide/images/prefixes-and-postfixes-config.png new file mode 100644 index 0000000..6ebb277 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/prefixes-and-postfixes-config.png differ diff --git a/generate-entities-from-db/text-based-guide/images/reverse-engineering.png b/generate-entities-from-db/text-based-guide/images/reverse-engineering.png new file mode 100644 index 0000000..bf25106 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/reverse-engineering.png differ diff --git a/generate-entities-from-db/text-based-guide/images/root-package-name.png b/generate-entities-from-db/text-based-guide/images/root-package-name.png new file mode 100644 index 0000000..759d416 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/root-package-name.png differ diff --git a/generate-entities-from-db/text-based-guide/images/select-new-fields-in-table.png b/generate-entities-from-db/text-based-guide/images/select-new-fields-in-table.png new file mode 100644 index 0000000..457f151 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/select-new-fields-in-table.png differ diff --git a/generate-entities-from-db/text-based-guide/images/select-one-of-possible-types.png b/generate-entities-from-db/text-based-guide/images/select-one-of-possible-types.png new file mode 100644 index 0000000..27bf24f Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/select-one-of-possible-types.png differ diff --git a/generate-entities-from-db/text-based-guide/images/select-primary-key-columns.png b/generate-entities-from-db/text-based-guide/images/select-primary-key-columns.png new file mode 100644 index 0000000..70164e6 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/select-primary-key-columns.png differ diff --git a/generate-entities-from-db/text-based-guide/images/select-table-posts.png b/generate-entities-from-db/text-based-guide/images/select-table-posts.png new file mode 100644 index 0000000..9d0c3d4 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/select-table-posts.png differ diff --git a/generate-entities-from-db/text-based-guide/images/select-view-from-db.png b/generate-entities-from-db/text-based-guide/images/select-view-from-db.png new file mode 100644 index 0000000..98ae736 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/select-view-from-db.png differ diff --git a/generate-entities-from-db/text-based-guide/images/spring-init.png b/generate-entities-from-db/text-based-guide/images/spring-init.png new file mode 100644 index 0000000..a806321 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/spring-init.png differ diff --git a/generate-entities-from-db/text-based-guide/images/superclass-name-and-attributes.png b/generate-entities-from-db/text-based-guide/images/superclass-name-and-attributes.png new file mode 100644 index 0000000..4279e32 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/superclass-name-and-attributes.png differ diff --git a/generate-entities-from-db/text-based-guide/images/to-posts-checkbox-checked.png b/generate-entities-from-db/text-based-guide/images/to-posts-checkbox-checked.png new file mode 100644 index 0000000..735e2ac Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/to-posts-checkbox-checked.png differ diff --git a/generate-entities-from-db/text-based-guide/images/youtube-thumbnail.png b/generate-entities-from-db/text-based-guide/images/youtube-thumbnail.png new file mode 100644 index 0000000..eac0797 Binary files /dev/null and b/generate-entities-from-db/text-based-guide/images/youtube-thumbnail.png differ