Въведение в ORM на Apache Cayenne

1. Общ преглед

Apache Cayenne е библиотека с отворен код, разпространявана под лиценза Apache, предоставяща функции като инструмент за моделиране, обектно-релационно картографиране, известен още като ORM за локални операции за постоянство и услуги за отдалечаване.

В следващите раздели ще видим как да взаимодействаме с база данни на MySQL, използвайки Apache Cayenne ORM.

2. Зависимости на Maven

За начало трябва само да добавим следните зависимости, за да изведем заедно Apache Cayenne и MySQL конектора JDBC драйвер за достъп до нашата база данни intro_cayenne :

 org.apache.cayenne cayenne-server 4.0.M5   mysql mysql-connector-java 5.1.44 runtime 

Нека конфигурираме приставката за моделиране на Cayenne, която ще се използва за проектиране или настройка на нашия файл за картографиране, който действа като мост между схемата на базата данни и обекта Java:

 org.apache.cayenne.plugins maven-cayenne-modeler-plugin 4.0.M5 

Вместо да създавате XML файл за картографиране на ръка (прави се рядко), препоръчително е да използвате модела, който е доста усъвършенстван инструмент, който се предлага с дистрибуцията на Cayenne.

Той е достъпен за изтегляне от този архив в зависимост от вашата операционна система или просто използвайте версията за различни платформи (JAR), включена като приставка Maven там.

Репозиторият Maven Central е домакин на най-новите версии на Apache Cayenne, неговия моделист и MySQL Connector.

След това нека изградим нашия проект с инсталирането на mvn и стартираме графичния интерфейс на модела с командата mvn cayenne-modeler: run, за да получим като изход този екран:

3. Настройка

За да накараме Apache Cayenne да потърси правилната локална база данни, трябва само да попълним конфигурационния му файл с правилния драйвер, URL адрес и потребител във файла cayenne-project.xml, намиращ се в директорията с ресурси :

Тук можем да видим, че:

  • Локалната база данни се нарича intro_cayenne
  • Ако все още не е създаден, Cayenne ще го направи вместо нас
  • Ще се свържете с помощта на потребителско име корен и парола корен (да го промените според потребителите, регистрирани в системата за управление на база данни)

Вътрешно е XMLPoolingDataSourceFactory отговорен за зареждането на информация за JDBC връзка от XML ресурс, свързан с DataNodeDescriptor .

Имайте предвид, че тези параметри са свързани със системата за управление на базата данни и JDBC драйвер, защото тази библиотека може да поддържа много различни бази данни.

Всеки от тях има адаптер, наличен в този подробен списък. Забележете, че пълната документация за версия 4.0 все още не е налице, затова се позоваваме на предишната версия тук.

4. Картиране и дизайн на база данни

4.1. Моделиране

Нека сега кликнете върху „Open Project“ , отидете до папката с ресурси на проекта и изберете файла cayenne-project.xml, моделът ще покаже това:

Тук имаме избор или да създадем нашата структура на картографиране от съществуваща база данни, или да продължим ръчно. Тази статия ще разгледа тази, която използва модела и съществуващата база данни, за да влезе в Cayenne и да разбере бързо как работи.

Нека да разгледаме нашата база данни intro_cayenne, която има връзка едно към много в две таблици, тъй като авторът може да публикува или притежава много статии:

  • автор: id (PK) и име
  • статия: id (PK), заглавие, съдържание и author_id (FK)

Сега нека отидем на „ Инструменти> Схема за реинженерна база данни “ и ще имаме автоматично конфигуриране на всички наши конфигурации за картографиране. На екрана за подкана просто попълнете конфигурацията на източника на данни, налична там във файла cayenne-project.xml, и натиснете continue:

На следващия екран трябва да проверим „Използване на примитивни типове Java“, както следва:

Трябва също да гарантираме? да поставите com.baeldung.apachecayenne.persistent като Java пакет и да го запазите; ще видим, че XML конфигурационният файл е актуализиран за свойството си defaultPackage, за да съответства на Java пакета:

Във всеки ObjEntity трябва да посочим пакета за подкласове, както е показано на следващото изображение, и да щракнем отново върху иконата “save” :

Сега в менюто „Инструменти> Генериране на класове“ изберете „ Стандартни постоянни обекти “ като тип; и в раздела „Класове“ проверете всички класове и натиснете „генериране“ .

Върни Нека до изходния код, за да видите, че нашите постоянни обекти са били генерирани успешно, говори за _Article.java и _Author.java .

Обърнете внимание, че всички тези конфигурации се записват във файла datamap.map.xml, който също се намира в папката с ресурси .

4.2. Структура на картографиране

Генерираният XML файл за картографиране, представен в папката с ресурси, използва някои уникални маркери спрямо Apache Cayenne:

  • DataNode () - моделът на базата данни, нейното съдържание, цялата информация, необходима за свързване към база данни (името на базата данни, драйвера и потребителските идентификационни данни)
  • DataMap () - това е контейнер от постоянни обекти с техните отношения
  • DbAttribute () - представлява колона в таблица на базата данни
  • DbEntity () - моделът на една таблица или изглед на база данни, той може да има DbAttributes и взаимоотношения
  • ObjEntity () - моделът на един постоянен java клас; направени от ObjAttributes, които съответстват на свойствата на класа на обекта и ObjRelationships, които са свойства, които имат тип на друг обект
  • Embeddable () - моделът на Java клас, който действа като свойство на ObjEntity, но съответства на множество колони в базата данни
  • Процедура () - за регистриране на съхранена процедура в базата данни
  • Query () - модел на заявка, използван за картографиране на заявка в конфигурационен файл, без да забравяме, че можем да го направим и в кода

Ето пълните подробности.

5. API на Cayenne

Единствената оставаща стъпка е да използваме API на Cayenne, за да извършваме нашите операции с база данни с помощта на генерирани класове, знаейки, че подкласирането на нашите постоянни класове е просто най-добрата практика, използвана за персонализиране на модела по-късно.

5.1. Създаване на обект

Тук просто записваме обект Автор и проверяваме по-късно дали в базата данни има само един запис от този тип:

@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.2. Четене на обект

After saving an Author, we just pick it among others via a simple query by a particular property:

@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.3. Retrieving All Records of a Class

We're going to save two authors and retrieve a collection of author objects to check that there are just these two saved:

@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 authors = ObjectSelect .query(Author.class) .select(context); assertEquals(2, authors.size()); }

5.4. Updating an Object

The updating process is easy too, but we need first to have the desired object before modifying its properties and applying it to the database:

@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.5. Attaching an Object

We can assign an article to an author:

@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()); }

5.6. Deleting an Object

The deletion of a saved object completely removes it from the database, thereafter we'll see null as the result of the query:

@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); }

5.7. Delete All Records of a Class

Също така е възможно да се изпуснат всички записи на таблица с помощта на SQLTemplate , тук правим това след всеки метод на теста, за да имаме винаги база данни с невалидни данни преди стартирането на всеки тест :

@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); }

6. Заключение

В този урок се съсредоточихме върху използването на Apache Cayenne ORM, за да демонстрираме лесно как да правим CRUD операции с връзка един към много .

Както винаги, изходният код за тази статия може да бъде намерен в GitHub.