1. 概要

Apache Cayenne は、Apacheライセンスの下で配布されるオープンソースライブラリであり、モデリングツール、ローカル永続化操作およびリモート処理サービス用のオブジェクトリレーショナルマッピング(別名ORM)などの機能を提供します。

次のセクションでは、ApacheCayenneORMを使用してMySQLデータベースと対話する方法を説明します。

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>

データベーススキーマとJavaオブジェクト間のブリッジとして機能するマッピングファイルの設計または設定に使用されるカイエンモデラープラグインを構成しましょう。

<plugin>
    <groupId>org.apache.cayenne.plugins</groupId>
    <artifactId>maven-cayenne-modeler-plugin</artifactId>
    <version>4.0.M5</version>
</plugin>

手作業でXMLマッピングファイルを作成する(めったに作成されない)代わりに、カイエンディストリビューションに付属する非常に高度なツールであるモデラーを使用することをお勧めします。

OSに応じて、このアーカイブからダウンロードできます。または、Mavenプラグインとして含まれているクロスプラットフォームバージョン(JAR)を使用することもできます。

Maven Centralリポジトリーは、 Apache Cayenne 彼のモデラー、および MySQLConnectorの最新バージョンをホストします。

次に、 mvn install を使用してプロジェクトをビルドし、コマンド mvn cayenne-modeler:run を使用してモデラーGUIを起動し、次の画面を出力として取得します。

3. 設定

Apache Cayenneに正しいローカルデータベースを検索させるには、リソースにあるファイル cayenne-project.xml に、適切なドライバー、URL、およびユーザーを構成ファイルに入力する必要があります。 ディレクトリ:

<?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です。
  • まだ作成されていない場合は、カイエンが代行してくれます
  • ユーザー名rootとパスワードrootを使用して接続します(データベース管理システムに登録されているユーザーに応じて変更してください)

内部的には、DataNodeDescriptorに関連付けられたXMLリソースからJDBC接続情報をロードするのはXMLPoolingDataSourceFactoryです。

このライブラリは多くの異なるデータベースをサポートできるため、これらのパラメータはデータベース管理システムとJDBCドライバに関連していることに注意してください。

それぞれに、この詳細なリストで利用可能なアダプターがあります。 バージョン4.0の完全なドキュメントはまだ利用できないため、ここでは以前のバージョンを参照していることに注意してください。

4. マッピングとデータベース設計

4.1. モデリング

次に、「プロジェクトを開く」をクリックし、プロジェクトのリソースフォルダーに移動して、ファイルcayenne-project.xmlを選択します。モデラーは次のように表示します。

ここでは、既存のデータベースからマッピング構造を作成するか 、手動で続行するかを選択できます。この記事では、モデラーと既存のデータベースを使用して、カイエンとそれがどのように機能するかをすばやく知っています。

著者は多くの記事を公開または所有できるため、2つのテーブル間で1対多の関係を持つintro_cayenneデータベースを見てみましょう。

  • 作成者:id(PK)および名前
  • 記事:id(PK)、タイトル、コンテンツ、および author_id(FK)

次に、「ツール>データベーススキーマのリエンジニアリング」に移動すると、すべてのマッピング構成が自動的に入力されます。 プロンプト画面で、 cayenne-project.xml ファイルにあるデータソース構成を入力し、[続行]をクリックします。

次の画面で、「Javaプリミティブ型を使用する」を次のようにチェックする必要があります。

また、 com.baeldung.apachecayenne.persistent をJavaパッケージとして配置し、保存する必要があります。 defaultPackage プロパティのXML構成ファイルが、Javaパッケージと一致するように更新されていることがわかります。

ObjEntityで、次の画像に示すようにサブクラスのパッケージを指定し、「保存」アイコンをもう一度クリックする必要があります。

次に、「ツール>クラスの生成」メニューで、タイプとして「標準永続オブジェクト」を選択します。 「クラス」タブですべてのクラスをチェックし、「生成」をクリックします。

ソースコードに戻って、永続オブジェクトが正常に生成されたことを確認し、_Article。java_Author。javaについて説明します。

これらの構成はすべて、resourcesフォルダーにもあるファイルdatamap.map.xmlに保存されていることに注意してください。

4.2. マッピング構造

リソースフォルダにある生成されたXMLマッピングファイルは、ApacheCayenneに関連するいくつかの一意のタグを使用しています。

  • DataNode( )。 –データベースのモデル、その内容データベースに接続するために必要なすべての情報(データベースの名前、ドライバー、およびユーザーの資格情報)
  • DataMap( )。 –それはそれらの関係を持つ永続的なエンティティのコンテナです
  • DbAttribute( )。 –データベーステーブルの列を表します
  • DbEntity( )。 –単一のデータベーステーブルまたはビューのモデル。DbAttributesとリレーションシップを持つことができます
  • ObjEntity( )。 –単一の永続的なJavaクラスのモデル。 エンティティクラスのプロパティに対応するObjAttributesと、別のエンティティのタイプを持つプロパティであるObjRelationshipsで構成されます
  • 埋め込み可能( )。 – ObjEntityのプロパティとして機能するが、データベース内の複数の列に対応するJavaクラスのモデル
  • 手順( )。 –ストアドプロシージャをデータベースに登録する
  • Query( )。 –クエリのモデル。コードでも実行できることを忘れずに、構成ファイルにクエリをマップするために使用されます。

これが完全な詳細です。

5. Cayenne API

残りの唯一のステップは、Cayenne APIを使用して、生成されたクラスを使用してデータベース操作を実行することです。永続クラスのサブクラス化は、後でモデルをカスタマイズするために使用されるベストプラクティスにすぎないことを知っています。

5.1. オブジェクトの作成

ここでは、 Author オブジェクトを保存し、後でデータベースにこのタイプのレコードが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. オブジェクトの読み取り

Author を保存した後、特定のプロパティによる単純なクエリを介して、特にそれを選択します。

@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. クラスのすべてのレコードを取得する

2人の作成者を保存し、作成者オブジェクトのコレクションを取得して、次の2人だけが保存されていることを確認します。

@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.4. オブジェクトの更新

更新プロセスも簡単ですが、プロパティを変更してデータベースに適用する前に、まず目的のオブジェクトを用意する必要があります。

@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. オブジェクトの添付

著者に記事を割り当てることができます:

@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. オブジェクトの削除

保存されたオブジェクトを削除すると、データベースから完全に削除されます。その後、クエリの結果としてnullが表示されます。

@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. クラスのすべてのレコードを削除する

SQLTemplate を使用してテーブルのすべてのレコードを削除することもできます。ここでは、各テストメソッドの後にこれを実行して、各テストが起動される前に常にvoidデータベースを作成します

@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を使用して、1対多の関係でCRUD操作を簡単に実行する方法を示すことに焦点を当てました。

いつものように、この記事のソースコードはGitHubにあります。