軽量O/Rマッピングフレームワーク ActiveObjects その1

RailsActiveRecordを意識したJavaの軽量ORMです。Entityとしてインターフェースを定義するだけで一通りのDB操作が可能で、XMLによる設定ファイル等なしで非常に手軽にORMを使うことができます。本家は以下です。
https://activeobjects.dev.java.net/
現在のバージョンは 0.8.2 となっています。

プロジェクトの準備

ここでは Maven にてプロジェクトを準備することにします(必要なライブラリも少ないため個々にjarを入手したほうが楽かもしれません)。
以下のコマンドでプロジェクトの雛形を作成します。

> mvn archetype:generate
Choose a number:・・ 15: :15
Define value for groupId: : etc9
Define value for artifactId: : activeobjects


mvn にて作成された pom.xml を以下のように修正し、「mvn eclipse:eclipse」にてeclipseプロジェクトに変換します。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>etc9</groupId>
  <artifactId>activeobjects</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>activeobjects</name>
  <url>http://maven.apache.org</url>
  <dependencies>

    <dependency>
      <groupId>net.java.dev.activeobjects</groupId>
      <artifactId>activeobjects</artifactId>
      <version>0.8.2</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.4</version>
      <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <version>1.8.0.7</version>
    </dependency>

  </dependencies>

  <repositories>
    <repository>
      <id>maven2-repository.dev.java.net</id>
      <name>Java.net Repository for Maven</name>
      <url>http://download.java.net/maven/2/</url>
      <layout>default</layout>
    </repository>
  </repositories>

</project>

H2は今のところサポート対象外なのでHSQLDBを使用することにしました。サポート対象のデータベースは以下を参照してください。
https://activeobjects.dev.java.net/supported.html
activeobjects はデフォルトのMavenリポジトリから取得できないため、別途repositoryを指定する必要があります。

以下ライブラリが取得されます。activeobjects の依存関係は ant のみです。

Entityの作成

テーブルのレコードに対応するEntityを作成します。Entityはインターフェースのみ定義するだけです。
net.java.ao.Entity を継承した Person インターフェースを作成します。

public interface Person extends Entity {
    public String getName();
    public void setName(String name);

    public int getAge();
    public void setAge(int age);
}

基本的にはこれだけです。

データベース操作

テストケースにて作成したPerson エンティテイを操作してみます。
まずはテストケースでHSQLDBの起動と停止の処理を書いておきます(後述のEntityManagerから直接起動はできなかったので)。

public class ActiveObjectsTest {
    
    private org.hsqldb.Server server;
    
    @Before
    public void before() {
        server = new Server();
        server.setDatabaseName(0, "test");
        server.setDatabasePath(0, "mem:test;sql.enforce_strict_size=true");
        server.setLogWriter(null);
        server.setErrWriter(null);
        server.start();
    }
    @After
    public void after() {
        server.stop();
    }
}

インメモリでHSQLDBサーバを起動しています。
ではPersonエンティテイを操作する処理をテストケースに追加していきます。

public class ActiveObjectsTest {
    ・・・
    @Test
    public void test() throws Exception {
        
        EntityManager em = new EntityManager("jdbc:hsqldb:hsql://localhost/test", "sa", "");
        em.migrate(Person.class);
        
        Person p1 = em.create(Person.class);
        p1.setName("Thome");
        p1.setAge(27);
        p1.save();

        Person p2 = em.create(Person.class);
        p2.setName("Mick");
        p2.setAge(52);
        p2.save();

        for(Person p : em.find(Person.class)) {
            System.out.println(p.getName() + ":" + p.getAge());
        }
}

em.migrate(Person.class) にてPersonインターフェースからテーブルを自動作成しています。これだけです。出力として以下が表示されていると思います。

Thome:27
Mick:52

Hibernate と比べると拍子抜けするぐらい簡単なのではないでしょうか。

検索条件の設定

前述のfind処理では全レコードを取得していましたが、ここでは検索条件を指定してみます。

    for (Person p : em.find(Person.class, "age >= ?", 30)) {
        System.out.println(p.getName() + ":" + p.getAge());
    }

以下のような結果となり、検索条件が有効となっていることが分かります。

Mick:52


直接SQLを指定することもできます。

em.findWithSQL(Person.class, "id", "SELECT id FROM person where age = ? ", 27)

findWithSQLの第2引数には通常プライマリキーを指定します(Personテーブルには自動的にidがプライマリキーとして定義されています)。


次回はEntity間の関連定義について見ていきます。