Reladomo (formerly known as Mithra) is an object-relational mapping (ORM) framework for Java, разработанный вGoldman Sachs, в настоящее время выпущен как проект с открытым исходным кодом. Каркас предоставляет функции, которые обычно необходимы в ORM, а также некоторые дополнительные.
Давайте посмотрим на некоторые ключевые особенностиReladomo:
он может генерировать классы Java, а также сценарии DDL
он управляется метаданными, записанными в файлах XML
сгенерированный код является расширяемым
язык запросов является объектно-ориентированным и строго типизированным
Фреймворк поддерживает Sharding (одна и та же схема, разные наборы данных).
поддержка тестирования также включена
он предоставляет полезные функции, такие как эффективное кэширование и транзакции
В следующих разделах мы увидим настройку и несколько основных примеров использования.
2. Maven Настройка
Чтобы начать использовать ORM, нам нужно добавить зависимостьreladomo в наш файлpom.xml:
com.goldmansachs.reladomoreladomo16.5.1
Мы будем использовать базу данныхH2 для наших примеров, поэтому давайте также добавим зависимостьh2:
com.h2databaseh21.4.196
In addition to this, we need to setup plugins that will generate classes and SQL files, и загрузить их во время выполнения.
Для генерации файлов мы можем использовать задачи, которые выполняются с использованиемmaven-antrun-plugin. Во-первых, давайте посмотрим, как мы можем определить задачу для генерации классов Java:
The gen-reladomo task uses the provided MithraGenerator to create Java files based on the configuration in ReladomoClassList.xml file. Мы подробнее рассмотрим, что содержит этот файл, в следующем разделе.
Задачи также имеют два свойства, которые определяют местоположение сгенерированных файлов:
generatedDir - содержит классы, которые нельзя изменять или версировать
nonGeneratedDir - сгенерированные классы конкретных объектов, которые могут быть дополнительно настроены и версированы
Таблицы базы данных, соответствующие объектам Java, могут быть созданы вручную или автоматически с помощью сценариев DDL, сгенерированных второй задачейAnt:
Эта задача используетMithraDbDefinitionGenerator на основе того же файлаReladomoClassList.xml, упомянутого ранее. Скрипты SQL будут помещены в каталогgenerated-db/sql.
Чтобы завершить определение этого плагина, мы также должны добавить две зависимости, используемые для создания:
Добавление сценариев DDL не является обязательным. В нашем примере мы будем использовать базу данных в памяти, поэтому мы хотим выполнить сценарии для создания таблиц.
3. Конфигурация XML
Метаданные для платформыReladomo могут быть определены в нескольких файлах XML.
3.1. XML-файлы объектов
Каждая сущность, которую мы хотим создать, должна быть определена в ее XML-файле.
Давайте создадим простой пример с двумя объектами: отделами и сотрудниками. Вот визуальное представление нашей модели предметной области:
Мы видим вышеthe entity is defined inside a root element called MithraObject. Затем мы указали пакет, класс и имя соответствующей таблицы базы данных.
Каждое свойство типа определяется с помощью элементаAttribute, для которого мы можем указать имя, тип Java и имя столбца.
We can describe the relationships between objects using the Relationship tag. В нашем примере мы определили связьone-to-many между объектамиDepartment иEmployee на основе выражения:
Employee.departmentId = this.id
АтрибутreverseRelationshipName можно использовать, чтобы сделать связь двунаправленной, не определяя ее дважды.
АтрибутrelatedIsDependent позволяет нам каскадировать операции.
Затем давайте создадим файлEmployee.xml аналогичным образом:
com.example.reladomoEmployeeemployees
3.2. ReladomoClassList.xml файл
Reladomo нужно сообщить об объектах, которые он должен генерировать.
В разделеMaven мы определили файлReladomoClassList.xml как источник для задач генерации, так что пора создать файл:
Это простой файл, содержащий список сущностей, для которых будут генерироваться классы на основе конфигурации XML.
4. Сгенерированные классы
Теперь у нас есть все элементы, необходимые для запуска генерации кода путем создания приложенияMaven с помощью командыmvn clean install.
Конкретные классы будут сгенерированы в папкеsrc/main/java указанного пакета:
Это простые классы, в которые мы можем добавить наш собственный код. Например, классDepartment содержит только конструктор, который не следует удалять:
public class Department extends DepartmentAbstract {
public Department() {
super();
// You must not modify this constructor. Mithra calls this internally.
// You can call this constructor. You can also add new constructors.
}
}
Если мы хотим добавить пользовательский конструктор в этот класс, он должен также вызвать родительский конструктор:
public Department(long id, String name){
super();
this.setId(id);
this.setName(name);
}
Эти классы основаны на абстрактных и служебных классах в папкеgenerated-sources/reladomo:
Основные типы классов в этой папке:
DepartmentAbstract иEmployeeAbstract классы - которые содержат методы для работы с определенными объектами
DepartmentListAbstract иEmployeeListAbstract - содержит методы для работы со списками отделов и сотрудников
DepartmentFinder иEmployeeFinder - они предоставляют методы для запроса сущностей
другие служебные классы
Создавая эти классы, мы уже создали большую часть кода, необходимого для выполнения операций CRUD над нашими сущностями.
5. Приложение Reladomo
Для выполнения операций с базой данных нам нужен класс диспетчера соединений, который позволяет нам получать соединения с базой данных.
5.1. Диспетчер подключений
При работе с одной базой данных мы можем реализовать интерфейсSourcelessConnectionManager:
public class ReladomoConnectionManager implements SourcelessConnectionManager {
private static ReladomoConnectionManager instance;
private XAConnectionManager xaConnectionManager;
public static synchronized ReladomoConnectionManager getInstance() {
if (instance == null) {
instance = new ReladomoConnectionManager();
}
return instance;
}
private ReladomoConnectionManager() {
this.createConnectionManager();
}
//...
}
Наш классReladomoConnectionManager реализует одноэлементный шаблон и основан наXAConnectionManager, который является служебным классом для диспетчера транзакционных соединений.
Это, конечно, не обязательно для производственного приложения, где ваши таблицы не будут воссозданы для каждого выполнения.
5.2. ИнициализацияReladomo
В процессе инициализацииReladomo используется файл конфигурации, в котором указывается класс диспетчера соединений и используемые типы объектов. Давайте определим файлReladomoRuntimeConfig.xml:
Затем мы можем создать основной класс, в котором сначала вызываем методcreateTables(), а затемuse the MithraManager class to load the configuration and initialize Reladomo:
Давайте теперь воспользуемся сгенерированнымиReladomo классами для выполнения нескольких операций с нашими сущностями.
Сначала создадим два объектаDepartment иEmployee, а затем сохраним их с помощью методаcascadeInsert():
Department department = new Department(1, "IT");
Employee employee = new Employee(1, "John");
department.getEmployees().add(employee);
department.cascadeInsert();
Каждый объект также можно сохранить отдельно, вызвав методinsert(). В нашем примере можно использоватьcascadeInsert(), потому что мы добавили атрибутrelatedIsDependent=true в определение отношения.
Для запроса объектов мы можем использовать сгенерированные классыFinder:
Department depFound = DepartmentFinder
.findByPrimaryKey(1);
Employee empFound = EmployeeFinder
.findOne(EmployeeFinder.name().eq("John"));
Полученные таким образом объекты являются «живыми» объектами, что означает, что любое изменение в них с использованием сеттеров немедленно отражается в базе данных:
empFound.setName("Steven");
Чтобы избежать такого поведения, мы можем получить отдельные объекты:
Department depDetached = DepartmentFinder
.findByPrimaryKey(1).getDetachedCopy();
Для удаления объектов мы можем использовать методdelete():
empFound.delete();
5.4. Управление транзакциями
Если мы хотим, чтобы набор операций выполнялся или не был одним целым, мы можем заключить их в транзакцию:
mithraManager.executeTransactionalCommand(tx -> {
Department dep = new Department(2, "HR");
Employee emp = new Employee(2, "Jim");
dep.getEmployees().add(emp);
dep.cascadeInsert();
return null;
});
6. Reladomo Тестовая поддержка
В разделах выше мы написали наши примеры в основном классе Java.
Если мы хотим написать тесты для нашего приложения, один из способов сделать это - просто написать один и тот же код в тестовом классе.
Однакоfor better test support, Reladomo also provides the MithraTestResource class. Это позволяет нам использовать другую конфигурацию и базу данных в памяти только для тестов.
Во-первых, нам нужно добавить дополнительную зависимостьreladomo-test-util вместе с зависимостьюjunit: