Apache Cayenne ORMの紹介

Apache Cayenne ORMの概要

1. 概要

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

次のセクションでは、Apache CayenneORMを使用してMySQLデータベースを操作する方法を説明します。

2. Mavenの依存関係

まず、次の依存関係を追加して、Apache CayenneとMySQLコネクタのJDBCドライバーを一緒に起動し、intro_cayenneデータベースにアクセスする必要があります。


    org.apache.cayenne
    cayenne-server
    4.0.M5


    mysql
    mysql-connector-java
    5.1.44
    runtime

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


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

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

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

Maven Centralリポジトリーは、最新バージョンのApache Cayennehis modeler、およびMySQL Connectorをホストします。

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

image

3. セットアップ

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



    
        
            
            
            
            
        
    

ここでそれを見ることができます:

  • ローカルデータベースの名前はintro_cayenneです。

  • まだ作成されていない場合は、Cayenneが作成します

  • ユーザー名rootとパスワードrootを使用して接続します(データベース管理システムに登録されているユーザーに応じて変更します)

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

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

それらのそれぞれには、この詳細なlistで使用可能なアダプターがあります。 バージョン4.0の完全なドキュメントはまだ入手できないため、ここでは以前のバージョンを参照します。

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

4.1. モデリング

次に、“Open Project”をクリックし、プロジェクトのリソースフォルダーに移動して、モデラーが表示するファイルcayenne-project.xml,を選択します。

image

ここで、we’ve got the choice to either create our mapping structure from an existing databaseor to proceed manually.この記事では、モデラーと既存のデータベースを使用してCayenneにアクセスし、それがどのように機能するかをすばやく理解します。

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

  • author: id (PK)およびname

  • article: id (PK), title, content、およびauthor_id(FK)

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

image

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

image

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

image

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

image

“Tools > Generate Classes”メニューで、タイプとして「Standard Persistent Objects」を選択します。 “Classes”タブですべてのクラスをチェックし、“generate”を押します。

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

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

4.2. マッピング構造

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

  • DataNode(<node>) –データベースのモデル、その内容データベースに接続するために必要なすべての情報(データベースの名前、ドライバー、およびユーザー資格情報)

  • DataMap(<data-map>) –それはそれらの関係を持つ永続的なエンティティのコンテナです

  • DbAttribute(<db-attribute>) –データベーステーブルの列を表します

  • DbEntity(<db-entity>) –単一のデータベーステーブルまたはビューのモデル。DbAttributesと関係を持つことができます

  • ObjEntity(<obj-entity>) –単一の永続Javaクラスのモデル。エンティティクラスのプロパティに対応するObjAttributesと、別のエンティティのタイプを持つプロパティであるObjRelationshipsで構成されます

  • Embeddable(<embeddable>) – ObjEntityのプロパティとして機能するが、データベース内の複数の列に対応するJavaクラスのモデル

  • Procedure(<procedure>) –ストアドプロシージャをデータベースに登録します

  • Query(<query>) –クエリのモデル。コードでも実行できることを忘れずに、構成ファイルにクエリをマップするために使用されます。

これが完全なdetailsです。

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

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