«1. Обзор
Apache Cayenne — это библиотека с открытым исходным кодом, распространяемая по лицензии Apache и предоставляющая такие функции, как инструмент моделирования, объектно-реляционное сопоставление, также известное как ORM, для операций локального сохранения и удаленных служб.
В следующих разделах мы увидим, как взаимодействовать с базой данных MySQL с помощью Apache Cayenne ORM.
2. Зависимости Maven
Для начала нам просто нужно добавить следующие зависимости, чтобы вызвать Apache Cayenne и MySQL, соединив драйвер JDBC вместе для доступа к нашей базе данных intro_cayenne:
<dependency>
<groupId>org.apache.cayenne</groupId>
<artifactId>cayenne-server</artifactId>
<version>4.0.M5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
<scope>runtime</scope>
</dependency>
Давайте настроим подключаемый модуль Cayenne modeler. который будет использоваться для разработки или настройки нашего файла сопоставления, который действует как мост между схемой базы данных и объектом Java:
<plugin>
<groupId>org.apache.cayenne.plugins</groupId>
<artifactId>maven-cayenne-modeler-plugin</artifactId>
<version>4.0.M5</version>
</plugin>
Вместо создания XML-файла сопоставления вручную (что делается редко) рекомендуется использовать средство моделирования довольно продвинутый инструмент, входящий в состав дистрибутива Cayenne.
Он доступен для загрузки из этого архива в зависимости от вашей ОС или просто используйте кросс-платформенную версию (JAR), включенную в качестве плагина Maven.
В репозитории Maven Central хранятся последние версии Apache Cayenne, его средства моделирования и MySQL Connector.
Далее давайте создадим наш проект с помощью mvn install и запустим графический интерфейс средства моделирования с помощью команды mvn cayenne-modeler:run, чтобы получить в качестве вывода этот экран:
3. Настройка
Чтобы заставить Apache Cayenne искать правильная локальная база данных, нам просто нужно заполнить его файл конфигурации с правильным драйвером, URL-адресом и пользователем в файле cayenne-project.xml, расположенном в каталоге ресурсов:
<?xml version="1.0" encoding="utf-8"?>
<domain project-version="9">
<node name="datanode"
factory
="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
schema-update-strategy
="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy">
<data-source>
<driver value="com.mysql.jdbc.Driver"/>
<url value
="jdbc:mysql://localhost:3306/intro_cayenne;create=true"/>
<connectionPool min="1" max="1"/>
<login userName="root" password="root"/>
</data-source>
</node>
</domain>
Здесь мы видим, что: ~~ ~ Локальная база данных называется intro_cayenne Если она еще не создана, Cayenne сделает это за нас Мы подключимся, используя имя пользователя root и пароль root (измените его в соответствии с пользователями, зарегистрированными в вашей системе управления базами данных)
-
Внутренне это XMLPoolingDataSourceFactory отвечает за загрузку информации о соединении JDBC из ресурса XML, связанного с DataNodeDescriptor.
Имейте в виду, что эти параметры относятся к системе управления базами данных и драйверу JDBC, поскольку эта библиотека может поддерживать множество различных баз данных.
У каждого из них есть адаптер, доступный в этом подробном списке. Обратите внимание, что полная документация для версии 4.0 еще недоступна, поэтому здесь мы ссылаемся на предыдущую версию.
4. Отображение и дизайн базы данных
4.1. Моделирование
Давайте теперь нажмем «Открыть проект», перейдите в папку ресурсов проекта и выберите файл cayenne-project.xml, моделлер покажет это:
Здесь, у нас есть выбор: либо создать нашу структуру сопоставления из существующей базы данных, либо продолжить работу вручную. В этой статье рассматривается тот, кто использует модельер и существующую базу данных, чтобы войти в Cayenne и быстро узнать, как это работает.
Давайте взглянем на нашу базу данных intro_cayenne, которая имеет отношение «один ко многим» между двумя таблицами, поскольку автор может публиковать или владеть многими статьями:
author: id (PK) и name article: id (PK) ), title, content и author_id(FK)
-
Теперь давайте перейдем в «Инструменты \u003e Реинжиниринг схемы базы данных», и все наши конфигурации сопоставления будут заполнены автоматически. На экране подсказки просто заполните конфигурацию источника данных, доступную там, в файле cayenne-project.xml, и нажмите «Продолжить»:
На следующем экране нам нужно отметить «Использовать примитивные типы Java». ‚¬ следующим образом:
Нам также необходимо поместить com.baeldung.apachecayenne.persistent в качестве пакета Java и сохранить его; мы увидим, что файл конфигурации XML был обновлен для свойства defaultPackage в соответствии с пакетом Java:
В каждом объекте ObjEntity мы должны указать пакет для подклассов, как показано на следующем рисунке, и нажать кнопку  значок «сохранить» снова:
Теперь в меню «Инструменты» \u003e «Создать классы» выберите «Стандартные постоянные объекты» в качестве типа; и на вкладке «Классы» проверьте все классы и нажмите «Создать».
Вернемся к исходному коду, чтобы увидеть, что наши постоянные объекты были успешно сгенерированы, говоря о _Article.java и _Author.java.
«Обратите внимание, что все эти конфигурации сохраняются в файле datamap.map.xml, который также находится в папке ресурсов.
4.2. Структура сопоставления
Сгенерированный XML-файл сопоставления, представленный в папке ресурсов, использует некоторые уникальные теги относительно Apache Cayenne:
DataNode(\u003cnode\u003e) — модель базы данных, ее содержимое, вся информация, необходимая для получения подключен к базе данных (имя базы данных, драйвер и учетные данные пользователя) DataMap(\u003cdata-map\u003e) — это контейнер постоянных сущностей с их отношениями DbAttribute(\u003cdb-attribute\u003e) — представляет столбец в таблице базы данных DbEntity(\u003cобъект-базы-данных\u003e) — модель отдельной таблицы или представления базы данных, может иметь атрибуты DbAttributes и связи. ObjEntity(\u003cобъект-сущность\u003e) — модель одного постоянного Java-класс; состоит из ObjAttributes, которые соответствуют свойствам класса сущностей, и ObjRelationships, которые являются свойствами, имеющими тип другой сущности. Embeddable(\u003cembeddable\u003e) — модель класса Java, которая действует как свойство ObjEntity, но соответствует нескольким столбцам. в базе данных. код
-
Вот полная информация.
5. Cayenne API
Единственный оставшийся шаг — использовать Cayenne API для выполнения операций с базой данных с использованием сгенерированных классов, зная, что создание подклассов для наших постоянных классов — это просто передовая практика, используемая для последующей настройки модели.
5.1. Создание объекта
Здесь мы просто сохраняем объект Author и позже проверяем, что в базе данных есть только одна запись этого типа:
5.2. Чтение объекта
@Test
public void whenInsert_thenWeGetOneRecordInTheDatabase() {
Author author = context.newObject(Author.class);
author.setName("Paul");
context.commitChanges();
long records = ObjectSelect.dataRowQuery(Author.class)
.selectCount(context);
assertEquals(1, records);
}
После сохранения автора мы просто выбираем его среди других с помощью простого запроса по определенному свойству:
5.3. Получение всех записей класса
@Test
public void whenInsert_andQueryByFirstName_thenWeGetTheAuthor() {
Author author = context.newObject(Author.class);
author.setName("Paul");
context.commitChanges();
Author expectedAuthor = ObjectSelect.query(Author.class)
.where(Author.NAME.eq("Paul"))
.selectOne(context);
assertEquals("Paul", expectedAuthor.getName());
}
Мы собираемся сохранить двух авторов и получить коллекцию объектов авторов, чтобы убедиться, что сохранены только эти два:
5.4. Обновление объекта
@Test
public void whenInsert_andQueryAll_thenWeGetTwoAuthors() {
Author firstAuthor = context.newObject(Author.class);
firstAuthor.setName("Paul");
Author secondAuthor = context.newObject(Author.class);
secondAuthor.setName("Ludovic");
context.commitChanges();
List<Author> authors = ObjectSelect
.query(Author.class)
.select(context);
assertEquals(2, authors.size());
}
Процесс обновления тоже прост, но нам нужно сначала получить желаемый объект, прежде чем изменять его свойства и применять его к базе данных:
5.5. Прикрепление объекта
@Test
public void whenUpdating_thenWeGetAnUpatedeAuthor() {
Author author = context.newObject(Author.class);
author.setName("Paul");
context.commitChanges();
Author expectedAuthor = ObjectSelect.query(Author.class)
.where(Author.NAME.eq("Paul"))
.selectOne(context);
expectedAuthor.setName("Garcia");
context.commitChanges();
assertEquals(author.getName(), expectedAuthor.getName());
}
Мы можем присвоить статье автора:
5.6. Удаление объекта
@Test
public void whenAttachingToArticle_thenTheRelationIsMade() {
Author author = context.newObject(Author.class);
author.setName("Paul");
Article article = context.newObject(Article.class);
article.setTitle("My post title");
article.setContent("The content");
article.setAuthor(author);
context.commitChanges();
Author expectedAuthor = ObjectSelect.query(Author.class)
.where(Author.NAME.eq("Smith"))
.selectOne(context);
Article expectedArticle = (expectedAuthor.getArticles()).get(0);
assertEquals(article.getTitle(), expectedArticle.getTitle());
}
Удаление сохраненного объекта полностью удаляет его из базы данных, после чего в результате запроса мы увидим null:
5.7. Удалить все записи класса
@Test
public void whenDeleting_thenWeLostHisDetails() {
Author author = context.newObject(Author.class);
author.setName("Paul");
context.commitChanges();
Author savedAuthor = ObjectSelect.query(Author.class)
.where(Author.NAME.eq("Paul"))
.selectOne(context);
if(savedAuthor != null) {
context.deleteObjects(author);
context.commitChanges();
}
Author expectedAuthor = ObjectSelect.query(Author.class)
.where(Author.NAME.eq("Paul"))
.selectOne(context);
assertNull(expectedAuthor);
}
Также можно удалить все записи таблицы с помощью SQLTemplate, здесь мы делаем это после каждого тестового метода, чтобы всегда иметь пустую базу данных перед запуском каждого теста:
6. Заключение
@After
public void deleteAllRecords() {
SQLTemplate deleteArticles = new SQLTemplate(
Article.class, "delete from article");
SQLTemplate deleteAuthors = new SQLTemplate(
Author.class, "delete from author");
context.performGenericQuery(deleteArticles);
context.performGenericQuery(deleteAuthors);
}
В этом руководстве мы сосредоточились на использовании Apache Cayenne ORM, чтобы легко продемонстрировать, как выполнять операции CRUD с отношением «один ко многим».
Как всегда, исходный код этой статьи можно найти на GitHub.
«