Reladomoの紹介

1概要

  • Reladomo(以前のMithra) は、 Goldman Sachs__で開発され、現在オープンソースプロジェクトとしてリリースされているJava用のオブジェクトリレーショナルマッピング(ORM)フレームワークです。 。フレームワークは、いくつかの追加の機能と同様に、ORMから一般的に必要とされる機能を提供します。

Reladomo の主な機能をいくつか見てみましょう。

  • DDLスクリプトだけでなくJavaクラスも生成可能

  • XMLファイルに書かれたメタデータによって動かされます

  • 生成されたコードは拡張可能です

  • 問い合わせ言語はオブジェクト指向で強く型付けされている

  • フレームワークはシャーディングのサポートを提供します(同じスキーマ、異なる

データセット) ** テストのサポートも含まれています

  • パフォーマンスキャッシングやトランザクションなどの便利な機能を提供します。

次のセクションでは、設定と基本的な使用例を紹介します。

2 天国 セットアップ

ORMを使い始めるには、 pom.xml ファイルに reladomo 依存関係を追加する必要があります。

<dependency>
    <groupId>com.goldmansachs.reladomo</groupId>
    <artifactId>reladomo</artifactId>
    <version>16.5.1</version>
</dependency>

例として H2 データベースを使用しますので、https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22h2%22%20AND%20g%3A%22comも追加します。 h2database%22[ h2 ]依存関係:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.196</version>
</dependency>
  • これに加えて、クラスとSQLファイルを生成するプラグインをセットアップし、実行中にそれらをロードする必要があります。

ファイル生成には、 maven-antrun-plugin を使って実行されるタスクを使うことができます。まず、Javaクラスを生成するためのタスクを定義する方法を見てみましょう。

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
            <id>generateMithra</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>run</goal>
            </goals>
            <configuration>
                <tasks>
                    <property name="plugin__classpath"
                      refid="maven.plugin.classpath"/>
                    <taskdef name="gen-reladomo"
                      classpath="plugin__classpath"
                      classname="com.gs.fw.common.mithra.generator.MithraGenerator"/>
                    <gen-reladomo
                      xml="${project.basedir}/src/main/resources/reladomo/ReladomoClassList.xml"
                      generateGscListMethod="true"
                      generatedDir="${project.build.directory}/generated-sources/reladomo"
                      nonGeneratedDir="${project.basedir}/src/main/java"/>
                </tasks>
            </configuration>
        </execution>
    </executions>
</plugin>
  • gen-reladomo タスクは提供された MithraGenerator を使用して ReladomoClassList.xml ファイルの設定に基づいてJavaファイルを作成します。** このファイルの内容については後のセクションで詳しく見ていきます。

タスクには、生成されたファイルの場所を定義する2つのプロパティもあります。

  • generatedDir - 変更してはいけないクラスや

バージョン管理 ** nonGeneratedDir - 生成可能な具象オブジェクトクラス

さらにカスタマイズおよびバージョン管理

Javaオブジェクトに対応するデータベーステーブルは、2番目の Ant タスクによって生成されたDDLスクリプトを使用して手動または自動で作成できます。

<taskdef
  name="gen-ddl"
  classname = "com.gs.fw.common.mithra.generator.dbgenerator.MithraDbDefinitionGenerator"
  loaderRef="reladomoGenerator">
    <classpath refid="maven.plugin.classpath"/>
</taskdef>
<gen-ddl
  xml="${project.basedir}/src/main/resources/reladomo/ReladomoClassList.xml"
  generatedDir="${project.build.directory}/generated-db/sql"
  databaseType="postgres"/>

このタスクでは、前述の ReladomoClassList.xml ファイルと同じ MithraDbDefinitionGenerator を使用します。 SQLスクリプトは generated-db/sql ディレクトリに配置されます。

このプラグインの定義を完成させるために、作成に使用される2つの依存関係も追加する必要があります。

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
   //...
    </executions>
    <dependencies>
        <dependency>
            <groupId>com.goldmansachs.reladomo</groupId>
            <artifactId>reladomogen</artifactId>
            <version>16.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.goldmansachs.reladomo</groupId>
            <artifactId>reladomo-gen-util</artifactId>
            <version>16.5.1</version>
        </dependency>
    </dependencies>
</plugin>

最後に、 build-helper-maven-plugin を使用して、生成されたファイルをクラスパスに追加できます。

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>${project.build.directory}/generated-sources/reladomo</source>
                </sources>
            </configuration>
        </execution>
        <execution>
            <id>add-resource</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>add-resource</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <directory>${project.build.directory}/generated-db/</directory>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

DDLスクリプトの追加はオプションです。この例では、インメモリデータベースを使用するので、テーブルを作成するためにスクリプトを実行します。

3 XML設定

Reladomo フレームワークのメタデータは、いくつかのXMLファイルで定義できます。

3.1. オブジェクトXMLファイル

作成したい各エンティティはXMLファイルで定義する必要があります。

部署と従業員という2つのエンティティからなる簡単な例を作成しましょう。これがドメインモデルの視覚的表現です。

リンク:/uploads/tables.png%20526w[]

最初の Department.xml ファイルを定義しましょう。

<MithraObject objectType="transactional">
    <PackageName>com.baeldung.reladomo</PackageName>
    <ClassName>Department</ClassName>
    <DefaultTable>departments</DefaultTable>

    <Attribute name="id" javaType="long"
      columnName="department__id" primaryKey="true"/>
    <Attribute name="name" javaType="String"
      columnName="name" maxLength="50" truncate="true"/>
    <Relationship name="employees" relatedObject="Employee"
      cardinality="one-to-many"
      reverseRelationshipName="department"
      relatedIsDependent="true">
         Employee.departmentId = this.id
    </Relationship>
</MithraObject>

上記のように、エンティティは MithraObject ** というルート要素内で定義されています。次に、パッケージ、クラス、および対応するデータベーステーブルの名前を指定しました。

型の各プロパティは Attribute 要素を使用して定義され、その名前、Java型、および列名を指定できます。

  • Relationship タグを使ってオブジェクト間の関係を記述することができます** この例では、次の式に基づいて Department オブジェクトと Employee オブジェクトの間に1対多の関係を定義しました。

Employee.departmentId = this.id
  • reverseRelationshipName 属性を使用すると、関係を2回定義せずに関係を双方向にすることができます。

relatedIsDependent 属性を使用すると、操作をカスケードできます。

次に、 Employee.xml ファイルを同じように作成しましょう。

<MithraObject objectType="transactional">
    <PackageName>com.baeldung.reladomo</PackageName>
    <ClassName>Employee</ClassName>
    <DefaultTable>employees</DefaultTable>

    <Attribute name="id" javaType="long"
      columnName="employee__id" primaryKey="true"/>
    <Attribute name="name" javaType="String"
      columnName="name" maxLength="50" truncate="true"/>
    <Attribute name="departmentId" javaType="long"
      columnName="department__id"/>
</MithraObject>

3.2. ReladomoClassList.xml ファイル

Reladomo は生成すべきオブジェクトについて知らされる必要があります。

Maven セクションでは、生成タスクのソースとして ReladomoClassList.xml ファイルを定義したので、次にファイルを作成します。

<Mithra>
    <MithraObjectResource name="Department"/>
    <MithraObjectResource name="Employee"/>
</Mithra>

これは、XML構成に基づいてクラスが生成されるエンティティのリストを含む単純なファイルです。

4生成されたクラス

これで、コマンド mvn clean install を使用して Maven アプリケーションをビルドすることによってコード生成を開始するために必要なすべての要素が揃いました。

具象クラスは、指定されたパッケージの src/main/java フォルダーに生成されます。

リンク:/uploads/classes.png[]

これらはカスタムコードを追加できる単純なクラスです。たとえば、 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 フォルダー内のabstractクラスとutilityクラスに基づいています。

リンク:/uploads/gen-classes.png%20303w[]

このフォルダ内のクラスの主な種類は次のとおりです。

  • DepartmentAbstract および EmployeeAbstract クラス - これには

定義されたエンティティを操作するためのメソッド ** DepartmentListAbstract および EmployeeListAbstract - これには

部署と従業員のリストを扱う方法 ** DepartmentFinder EmployeeFinder - これらは以下のメソッドを提供します。

エンティティの照会 ** 他のユーティリティクラス

これらのクラスを生成することによって、私たちのエンティティに対してCRUD操作を実行するのに必要なコードの大部分は、私たちのためにすでに作成されています。

5 Reladomoアプリケーション

データベースで操作を実行するには、データベース接続を取得できるようにする接続マネージャクラスが必要です。

5.1. 接続マネージャ

単一のデータベースを扱う場合は、 SlesslessConnectionManager インターフェースを実装できます。

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 に基づいています。

createConnectionManager() メソッドを詳しく見てみましょう。

private XAConnectionManager createConnectionManager() {
    xaConnectionManager = new XAConnectionManager();
    xaConnectionManager.setDriverClassName("org.h2.Driver");
    xaConnectionManager.setJdbcConnectionString("jdbc:h2:mem:myDb");
    xaConnectionManager.setJdbcUser("sa");
    xaConnectionManager.setJdbcPassword("");
    xaConnectionManager.setPoolName("My Connection Pool");
    xaConnectionManager.setInitialSize(1);
    xaConnectionManager.setPoolSize(10);
    xaConnectionManager.initialisePool();
    return xaConnectionManager;
}

このメソッドでは、 H2 インメモリデータベースへの接続を作成するために必要なプロパティを設定します。

また、 SlesslessConnectionManager インターフェースからいくつかのメソッドを実装する必要があります。

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

最後に、データベーステーブルを作成する生成されたDDLスクリプトを実行するためのカスタムメソッドを追加しましょう。

public void createTables() throws Exception {
    Path ddlPath = Paths.get(ClassLoader.getSystemResource("sql").toURI());
    try (
      Connection conn = xaConnectionManager.getConnection();
      Stream<Path> list = Files.list(ddlPath)) {

        list.forEach(path -> {
            try {
                RunScript.execute(conn, Files.newBufferedReader(path));
            }
            catch (SQLException | IOException exc){
                exc.printStackTrace();
            }
        });
    }
}

もちろん、これは実行時にテーブルが再作成されるわけではない本番アプリケーションには必要ありません。

5.2. Reladomo を初期化しています

Reladomo 初期化プロセスは、接続マネージャクラスと使用されるオブジェクトタイプを指定する設定ファイルを使用します。 ReladomoRuntimeConfig.xml ファイルを定義しましょう。

<MithraRuntime>
    <ConnectionManager
      className="com.baeldung.reladomo.ReladomoConnectionManager ">
    <MithraObjectConfiguration
      className="com.baeldung.reladomo.Department" cacheType="partial"/>
    <MithraObjectConfiguration
      className="com.baeldung.reladomo.Employee " cacheType="partial"/>
    </ConnectionManager>
</MithraRuntime>

次に、最初に createTables() メソッドを呼び出すメインクラスを作成し、次に MithraManager クラスを使用して設定を読み込み、 Reladomo ** を初期化します。

public class ReladomoApplication {
    public static void main(String[]args) {
        try {
            ReladomoConnectionManager.getInstance().createTables();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        MithraManager mithraManager = MithraManagerProvider.getMithraManager();
        mithraManager.setTransactionTimeout(120);

        try (InputStream is = ReladomoApplication.class.getClassLoader()
          .getResourceAsStream("ReladomoRuntimeConfig.xml")) {
            MithraManagerProvider.getMithraManager()
              .readConfiguration(is);

           //execute operations
        }
        catch (IOException exc){
            exc.printStackTrace();
        }
    }
}

5.3. CRUD操作を実行する

それでは、__Reladomoで生成されたクラスを使用して、私たちのエンティティに対していくつかの操作を実行しましょう。

まず、2つの Department オブジェクトと Employee オブジェクトを作成し、次に cascadeInsert() メソッドを使用して両方を保存します。

Department department = new Department(1, "IT");
Employee employee = new Employee(1, "John");
department.getEmployees().add(employee);
department.cascadeInsert();

各オブジェクトは、 insert() メソッドを呼び出すことによって個別に保存することもできます。この例では、 relatedIsDependent = true 属性をリレーション定義に追加したため、 cascadeInsert() を使用することができます。

  • オブジェクトを問い合わせるために、生成された 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. 取引管理

一連の操作を1つの単位として実行したくない場合は、トランザクションでラップできます。

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のメインクラスで書きました。

アプリケーション用にテストを書きたい場合、これを行う1つの方法は、単純にテストクラスに同じコードを書くことです。

ただし、 テストサポートを改善するために、Reladomoは MithraTestResource クラスも提供しています これにより、テスト用に異なる構成とインメモリデータベースを使用できます。

まず、 reladomo-test-util 依存関係を追加します。 junit 依存関係:

<dependency>
    <groupId>com.goldmansachs.reladomo</groupId>
    <artifactId>reladomo-test-util</artifactId>
    <version>16.5.1</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

次に、 ConnectionManagerForTests クラスを使用する ReladomoTestConfig.xml ファイルを作成する必要があります。

<MithraRuntime>
    <ConnectionManager
      className="com.gs.fw.common.mithra.test.ConnectionManagerForTests">
        <Property name="resourceName" value="testDb"/>
        <MithraObjectConfiguration
          className="com.baeldung.reladomo.Department" cacheType="partial"/>
        <MithraObjectConfiguration
          className="com.baeldung.reladomo.Employee " cacheType="partial"/>
    </ConnectionManager>
 </MithraRuntime>

この接続マネージャは、テストにのみ使用されるインメモリ H2 データベースを構成します。

  • MithraTestResource クラスの便利な機能は、テキストファイルに次の形式でテストデータを** 提供できることです。

class com.baeldung.reladomo.Department
id, name
1, "Marketing"

class com.baeldung.reladomo.Employee
id, name
1, "Paul"

JUnit テストクラスを作成し、 @ Before メソッドで MithraTestResource インスタンスを設定しましょう。

public class ReladomoTest {
    private MithraTestResource mithraTestResource;

    @Before
    public void setUp() throws Exception {
        this.mithraTestResource
          = new MithraTestResource("reladomo/ReladomoTestConfig.xml");

        ConnectionManagerForTests connectionManager
          = ConnectionManagerForTests.getInstanceForDbName("testDb");
        this.mithraTestResource.createSingleDatabase(connectionManager);
        mithraTestResource.addTestDataToDatabase("reladomo/test-data.txt",
          connectionManager);

        this.mithraTestResource.setUp();
    }
}

それからテストデータがロードされたことを検証する簡単な @ Test メソッドを書くことができます。

@Test
public void whenGetTestData__thenOk() {
    Employee employee = EmployeeFinder.findByPrimaryKey(1);
    assertEquals(employee.getName(), "Paul");
}

テストが実行された後、テストデータベースはクリアされる必要があります:

@After
public void tearDown() throws Exception {
    this.mithraTestResource.tearDown();
}

7. 結論

この記事では、 Reladomo ORMフレームワークの主な機能、および一般的な使用方法の設定と例について説明しました。

例のソースコードはhttps://github.com/eugenp/tutorials/tree/master/libraries-data[GitHubに追加]で見つけることができます。