Reladomo (formerly known as Mithra) is an object-relational mapping (ORM) framework for Java, entwickelt beiGoldman Sachs, derzeit als Open-Source-Projekt veröffentlicht. Das Framework bietet die Funktionen, die üblicherweise von einem ORM benötigt werden, sowie einige zusätzliche Funktionen.
Sehen wir uns einige der wichtigsten Funktionen vonReladomo an:
Es können sowohl Java-Klassen als auch DDL-Skripte generiert werden
Es wird von Metadaten gesteuert, die in XML-Dateien geschrieben wurden
Der generierte Code ist erweiterbar
Die Abfragesprache ist objektorientiert und stark typisiert
Das Framework bietet Unterstützung für das Sharding (dasselbe Schema, verschiedene Datasets)
Die Unterstützung für das Testen ist ebenfalls enthalten
Es bietet nützliche Funktionen wie Performant Caching und Transaktionen
In den folgenden Abschnitten sehen wir das Setup und einige grundlegende Anwendungsbeispiele.
2. Maven Setup
Um das ORM verwenden zu können, müssen wir die Abhängigkeit vonreladomozu unserer Datei vonpom.xmlhinzufügen:
com.goldmansachs.reladomoreladomo16.5.1
Wir werden für unsere Beispiele eineH2-Datenbank verwenden. Fügen wir also auch dieh2-abhängigkeit hinzu:
com.h2databaseh21.4.196
In addition to this, we need to setup plugins that will generate classes and SQL files und laden Sie sie während der Ausführung.
Für die Dateierzeugung können wir Aufgaben verwenden, die mitmaven-antrun-pluginausgeführt werden. Lassen Sie uns zunächst sehen, wie wir die Aufgabe zum Generieren von Java-Klassen definieren können:
The gen-reladomo task uses the provided MithraGenerator to create Java files based on the configuration in ReladomoClassList.xml file. Wir werden uns in einem späteren Abschnitt genauer ansehen, was diese Datei enthält.
Die Aufgaben haben auch zwei Eigenschaften, die den Speicherort der generierten Dateien definieren:
generatedDir - enthält die Klassen, die nicht geändert oder versioniert werden sollten
nonGeneratedDir - die generierten konkreten Objektklassen, die weiter angepasst und versioniert werden können
Die Datenbanktabellen, die den Java-Objekten entsprechen, können entweder manuell oder automatisch mithilfe der DDL-Skripte erstellt werden, die von einer zweitenAnt-Aufgabe generiert wurden:
Diese Aufgabe verwendetMithraDbDefinitionGenerator basierend auf derselbenReladomoClassList.xml-Datei, die zuvor erwähnt wurde. Die SQL-Skripte werden im Verzeichnisgenerated-db/sqlabgelegt.
Um die Definition für dieses Plugin zu vervollständigen, müssen zwei Abhängigkeiten hinzugefügt werden, die für die Erstellung verwendet werden:
Das Hinzufügen der DDL-Skripte ist optional. In unserem Beispiel verwenden wir eine In-Memory-Datenbank. Daher möchten wir die Skripte ausführen, um die Tabellen zu erstellen.
3. XML-Konfiguration
Die Metadaten für dasReladomo-Framework können in mehreren XML-Dateien definiert werden.
3.1. Objekt-XML-Dateien
Jede Entität, die wir erstellen möchten, muss in ihrer XML-Datei definiert werden.
Lassen Sie uns ein einfaches Beispiel mit zwei Entitäten erstellen: Abteilungen und Mitarbeiter. Hier ist eine visuelle Darstellung unseres Domain-Modells:
Wir können überthe entity is defined inside a root element called MithraObject sehen. Anschließend haben wir das Paket, die Klasse und den Namen der entsprechenden Datenbanktabelle angegeben.
Jede Eigenschaft des Typs wird mit einemAttribute-Element definiert, für das wir den Namen, den Java-Typ und den Spaltennamen angeben können.
We can describe the relationships between objects using the Relationship tag. In unserem Beispiel haben wir eineone-to-many-Beziehung zwischenDepartment undEmployee Objekten basierend auf dem Ausdruck definiert:
Employee.departmentId = this.id
Das AttributreverseRelationshipName kann verwendet werden, um die Beziehung bidirektional zu gestalten, ohne sie zweimal zu definieren.
Das AttributrelatedIsDependent ermöglicht es uns, Operationen zu kaskadieren.
Als Nächstes erstellen wir dieEmployee.xml-Datei auf ähnliche Weise:
com.example.reladomoEmployeeemployees
3.2. ReladomoClassList.xml Datei
Reladomo muss über die Objekte informiert werden, die generiert werden sollen.
Im AbschnittMaven haben wir die DateiReladomoClassList.xml als Quelle für die Generierungsaufgaben definiert. Daher ist es an der Zeit, die Datei zu erstellen:
Dies ist eine einfache Datei, die eine Liste von Entitäten enthält, für die Klassen basierend auf der XML-Konfiguration generiert werden.
4. Generierte Klassen
Jetzt haben wir alle Elemente, die wir zum Starten der Codegenerierung benötigen, indem wir die AnwendungMavenmit dem Befehlmvn clean install erstellen.
Die konkreten Klassen werden im Ordnersrc/main/java im angegebenen Paket generiert:
Dies sind einfache Klassen, in denen wir unseren benutzerdefinierten Code hinzufügen können. Beispielsweise enthält die KlasseDepartmentnur einen Konstruktor, der nicht entfernt werden sollte:
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.
}
}
Wenn wir dieser Klasse einen benutzerdefinierten Konstruktor hinzufügen möchten, muss auch der übergeordnete Konstruktor aufgerufen werden:
public Department(long id, String name){
super();
this.setId(id);
this.setName(name);
}
Diese Klassen basieren auf den Abstract- und Utility-Klassen im Ordnergenerated-sources/reladomo:
Die Hauptklassen in diesem Ordner sind:
KlassenDepartmentAbstract undEmployeeAbstract - enthält Methoden zum Arbeiten mit den definierten Entitäten
DepartmentListAbstract undEmployeeListAbstract - enthält Methoden zum Arbeiten mit Listen von Abteilungen und Mitarbeitern
DepartmentFinder undEmployeeFinder - diese bieten Methoden zum Abfragen von Entitäten
andere Gebrauchsklassen
Durch das Generieren dieser Klassen wird bereits ein großer Teil des Codes, der zum Ausführen von CRUD-Operationen für unsere Entitäten erforderlich ist, für uns erstellt.
5. Reladomo-Anwendung
Um Vorgänge in der Datenbank ausführen zu können, benötigen wir eine Verbindungsmanagerklasse, mit der wir Datenbankverbindungen erhalten können.
5.1. Verbindungsmanager
Wenn wir mit einer einzelnen Datenbank arbeiten, können wir dieSourcelessConnectionManager-Schnittstelle implementieren:
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();
}
//...
}
UnsereReladomoConnectionManager-Klasse implementiert das Singleton-Muster und basiert auf einemXAConnectionManager, einer Dienstprogrammklasse für einen Transaktionsverbindungsmanager.
Schauen wir uns die MethodecreateConnectionManager()genauer an:
Bei dieser Methode legen wir die Eigenschaften fest, die zum Herstellen einer Verbindung zu einer speicherinternenH2-Datenbank erforderlich sind.
Außerdem müssen wir verschiedene Methoden über dieSourcelessConnectionManager-Schnittstelle implementieren:
@Override
public Connection getConnection() {
return xaConnectionManager.getConnection();
}
@Override
public DatabaseType getDatabaseType() {
return H2DatabaseType.getInstance();
}
@Override
public TimeZone getDatabaseTimeZone() {
return TimeZone.getDefault();
}
@Override
public String getDatabaseIdentifier() {
return "myDb";
}
@Override
public BulkLoader createBulkLoader() throws BulkLoaderException {
return null;
}
Fügen Sie abschließend eine benutzerdefinierte Methode hinzu, um die generierten DDL-Skripts auszuführen, mit denen unsere Datenbanktabellen erstellt werden:
Dies ist natürlich nicht für eine Produktionsanwendung erforderlich, bei der Ihre Tabellen nicht bei jeder Ausführung neu erstellt werden.
5.2. Reladomo wird initialisiert
Der Initialisierungsprozess vonReladomoverwendet eine Konfigurationsdatei, die die Verbindungsmanagerklasse und die verwendeten Objekttypen angibt. Definieren wir eineReladomoRuntimeConfig.xml-Datei:
Als nächstes können wir eine Hauptklasse erstellen, in der wir zuerst die MethodecreateTables() und dannuse the MithraManager class to load the configuration and initialize Reladomo aufrufen:
Verwenden wir jetzt die vonReladomo generierten Klassen, um einige Operationen an unseren Entitäten auszuführen.
Zuerst erstellen wir zweiDepartment- undEmployee-Objekte und speichern dann beide mit dercascadeInsert()-Methode:
Department department = new Department(1, "IT");
Employee employee = new Employee(1, "John");
department.getEmployees().add(employee);
department.cascadeInsert();
Jedes Objekt kann auch separat gespeichert werden, indem die Methodeinsert()aufgerufen wird. In unserem Beispiel ist es möglich,cascadeInsert() zu verwenden, da wir das AttributrelatedIsDependent=true zu unserer Beziehungsdefinition hinzugefügt haben.
Zum Abfragen von Objekten können wir die generiertenFinder-Klassen verwenden:
Department depFound = DepartmentFinder
.findByPrimaryKey(1);
Employee empFound = EmployeeFinder
.findOne(EmployeeFinder.name().eq("John"));
Die Objekte, die auf diese Weise erhalten werden, sind "lebende" Objekte, was bedeutet, dass jede Änderung an ihnen unter Verwendung von Setzern sofort in der Datenbank wiedergegeben wird:
empFound.setName("Steven");
Um dieses Verhalten zu vermeiden, können wir getrennte Objekte erhalten:
Department depDetached = DepartmentFinder
.findByPrimaryKey(1).getDetachedCopy();
Um Objekte zu entfernen, können wir die Methodedelete()verwenden:
empFound.delete();
5.4. Transaktionsmanagement
Wenn wir möchten, dass eine Gruppe von Operationen als eine Einheit ausgeführt wird oder nicht, können wir sie in eine Transaktion einschließen:
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 Testunterstützung
In den obigen Abschnitten haben wir unsere Beispiele in einer Java-Hauptklasse geschrieben.
Wenn wir Tests für unsere Anwendung schreiben möchten, besteht eine Möglichkeit darin, einfach denselben Code in eine Testklasse zu schreiben.
for better test support, Reladomo also provides the MithraTestResource class. Dies ermöglicht es uns, nur für die Tests eine andere Konfigurations- und In-Memory-Datenbank zu verwenden.
Zuerst müssen wir die zusätzliche Abhängigkeit vonreladomo-test-utilzusammen mit der Abhängigkeit vonjunithinzufügen: