Представим, что вашему проекту срочно понадобился ORM, и вы хотите внедрить его как можно быстрее. В этой статье я хочу рассказать, как это можно сделать всего за четыре шага на примере использования open source проекта Apache Cayenne.
Для начала вкратце опишу механизм работы с данной библиотекой. Схема базы данных и модели описывается в xml файле, который может быть сгенерирован через GUI приложение или через консоль. Затем на основе xml файла генерируются java объекты, которые являются соответствующим отображением таблиц в базе. Последним шагом создается ServerRuntime
— объект, который инкапсулирует в себе весь стек Apache Cayenne.
Итак, перейдем к примеру. Что необходимо сделать:
- Создать схему базы данных
- Импортировать схему в проект, то есть получить xml файлы с описанием схемы
- Создать объектную модель, то есть сгенерировать java классы
- Проинициализировать
ServerRuntime
для доступа к базе данных из приложения
Что потребуется для начала? Уже существующий maven или gradle проект, Java 1.8+ и база данных. Мой тестовый проект использует maven, java 14 и самую свежую версию Apache Cayenne 4.2.M1. В качестве базы я использую mysql. Вы для своих проектов можете использовать стабильную версию 4.1 и любую из известных реляционных баз на ваш выбор.
Для наглядности я прикреплю ссылку на пример.
Создание схемы
Для примера создадим простейшую схему, состоящую из трех сущностей: марка авто, модель авто, отзыв на модель авто.
CREATE SCHEMA IF NOT EXISTS cars_demo; USE cars_demo; CREATE TABLE car_brand (ID INT NOT NULL AUTO_INCREMENT, NAME VARCHAR(200) NULL, COUNTRY VARCHAR(200) NULL, PRIMARY KEY (ID)) ENGINE=InnoDB; CREATE TABLE car_model (ID INT NOT NULL AUTO_INCREMENT, NAME VARCHAR(200) NULL, CAR_BRAND_ID INT NULL, PRIMARY KEY (ID)) ENGINE=InnoDB; CREATE TABLE feedback (CAR_MODEL_ID INT NULL, ID INT NOT NULL AUTO_INCREMENT, FEEDBACK VARCHAR(200) NULL, PRIMARY KEY (ID)) ENGINE=InnoDB; ALTER TABLE car_model ADD FOREIGN KEY (CAR_BRAND_ID) REFERENCES car_brand (ID) ON DELETE CASCADE; ALTER TABLE feedback ADD FOREIGN KEY (CAR_MODEL_ID) REFERENCES car_model (ID) ON DELETE CASCADE;
Первый шаг пройден, двигаемся ко второму.
Импорт схемы
Здесь уже начинается непосредственное использование библиотеки. Для начала подключим необходимый плагин к проекту:
<plugin> <groupId>org.apache.cayenne.plugins</groupId> <artifactId>cayenne-maven-plugin</artifactId> <version>${cayenne.version}</version> <configuration> <dataSource> <!--1--> <driver>com.mysql.jdbc.Driver</driver> <url>jdbc:mysql://127.0.0.1:3306/cars_demo</url> <username>root</username> <password>root</password> </dataSource> <cayenneProject>${project.basedir}/src/main/resources/cayenne/cayenne-project.xml</cayenneProject> <!--2--> <map>${project.basedir}/src/main/resources/cayenne/datamap.map.xml</map> <!--3--> <dbImport> <!--4--> <defaultPackage>cayenne.note.project.model</defaultPackage> <catalog>cars_demo</catalog> </dbImport> </configuration> <dependencies> <dependency> <!--5--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> </dependencies> </plugin>
- (1) DataSource, для подключения к базе
- (2) Путь, где будет лежать сгенерированный xml, который необходим для запуска Cayenne
- (3) Путь, где будет лежать xml с описанием модели и базы
- (4) Базовый пакет, где позже будут находиться сгенерированные классы
- (5) Зависимость от mysql-connector для работы с mysql
Далее в консоли запускаем импорт модели:
mvn cayenne:cdbimport
После выполнения этой команды должны появится два файла, указанные в (2) и (3). Как я уже говорил, файл cayenne-project.xml является служебным файлом, необходимым для работы библиотеки. Файл datamap.map.xml — это описание модели базы данных и ее объектного отображения, а также всех связей.
Пару слов о процессе cdbimport
: по умолчанию он импортирует всю схему, включая все связи. Данная команда может быть кастомизирована. Вы можете указать, какие сущности стоит включить в импорт, какие исключить, есть возможность указать паттерн для импорта таблиц. Более подробно с этим можно ознакомиться в документации.
Генерация классов
В предыдущем пункте мы сгенерировали описание модели, теперь же нам необходимо сгенерировать java классы, которые можно будет использовать в проекте. Сделать это очень просто, достаточно просто запустить в консоли команду:
mvn cayenne:cgen
После успешной генерации в пакете, который был указан в настройке плагина, будет находиться набор сгенерированных сущностей. Стоит обратить внимание, что сгенерировалось два набора классов. Первый находится в пакете auto
и является служебным. Не стоит модифицировать эти классы, так как все изменения исчезнут при следующей генерации. Для пользовательских изменений существуют классы без нижнего подчеркивания, которые наследуются от классов из пакета auto
. Именно они предназначаются для прямого использования и кастомизации.
Пример использования
Мы на финишной прямой, осталось только привести пример использования Apache Cayenne.
Создадим ServerRuntime
— это основной стэк Cayenne, который создается один раз для всего проекта.
Из рантайма всегда можно получить ObjectContext
— объект, который используется для работы с базой данных.
ServerRuntime cayenneRuntime = ServerRuntime.builder() .dataSource(DataSourceBuilder .url("jdbc:mysql://127.0.0.1:3306/cars_demo") .driver("com.mysql.cj.jdbc.Driver") .userName("root") // Need to change to your username .password("root") // Need to change to your password .build()) .addConfig("cayenne/cayenne-project.xml") .build(); ObjectContext context = cayenneRuntime.newContext();
Создадим несколько сущностей и отправим их в базу:
CarBrand carBrand = context.newObject(CarBrand.class); carBrand.setName("BMW"); carBrand.setCountry("Germany"); CarModel carModel = context.newObject(CarModel.class); carModel.setName("i3"); carModel.setCarBrand(carBrand); Feedback feedback = context.newObject(Feedback.class); feedback.setFeedback("Like"); feedback.setCarModel(carModel); context.commitChanges();
Как видно, мы создаем объекты при помощи ObjectContext
, затем модифицируем их и фиксируем изменения при помощи context.commitChanges()
.
Для выборки сущностей можно использовать API на любой вкус от чистого sql и ejbql до хорошо читаемого API. Полное описание можно найти в документации.
Небольшой пример обычного селекта из базы с использованием Apache Cayenne:
List<CarBrand> carBrans = ObjectSelect.query(CarBrand.class).select(context);
На этом у меня все. Как видно из этого примера, за несколько шагов можно получить боевой ORM, который полностью готов к работе. Надеюсь статья оказалась полезной. С полным примером можно ознакомиться здесь.
ссылка на оригинал статьи https://habr.com/ru/post/519470/