ORM比較(1) - ActiveObjects

ActiveObjectsは、Ruby on RailsActiveRecordの考え方を元にしていて、XMLを使わずに全てJavaで記述できるORMです。CoCを重視するので、テーブル構造などは基本的に ActiveRecordと同じようにキー項目は id固定で、ORMのユーザ側からは操作しない前提になっています。
公式ページは https://activeobjects.dev.java.net/ になってます。

動かすために必要なライブラリは、以下の3つだけです。

  • activeobjects-0.8.2.jar (ActiveObjecects)
  • c3p0-0.9.1.2.jar (C3P0 コネクションプーリングするためのライブラリ)
  • postgresql-8.3-603.jdbc4.jar (PostgreSQLJDBCドライバ)

そんな訳でさっそくソースを。
Entityクラスは、net.java.ao.Entityを継承して作ります。テーブル名や列名はクラス名及びgetter・setterの名前から自動的に決まります(つまり CoCですね)。ただし、アノテーションを付けることで自分で指定することも可能です。

ユーザマスタ(テーブル名はMUser)のEntity

public interface MUser extends Entity {
	@Unique
	String getName();
	void setName(String name);

	String getPassword();
	void setPassword(String password);

	MUserGroup getUserGroup();
	void setUserGroup(MUserGroup gruop);
}

ユーザグループ(テーブル名はMUserGroup)のEntity

public interface MUserGroup extends Entity {
	@Unique
	String getName();
	void setName(String name);

	@OneToMany
	MUser[] getUsers();
}

次に、コネクションの作成部分をSingletonな実装にしておきます。ここで接続設定を定数に記述してますが、実際に使う場合には適宜設定ファイルから読み出すようにすることになるでしょう。

public class EntityManagerFactory {
	/// DBのアドレスは適当に設定
	private static final String DB_URI = "jdbc:postgresql://192.168.3.20:5432/sample_test";
	private static final String DB_USER = "postgres";
	private static final String DB_PASS = "postgres";

	private static final EntityManager instance_ = new EntityManager(DB_URI, DB_USER, DB_PASS);
	static {
		// ActiveObjects内部のログを出力するためにログレベルを変更
		java.util.logging.Logger.getLogger("net.java.ao").setLevel(java.util.logging.Level.FINE);
	}

	public static EntityManager getInstance() {
		return instance_;
	}
}

最後に、実際にORMを使う部分のソースです。データの取得は、EntityManager#findを使います。Genericなメソッドになっているため、型安全にデータを取得できるので嬉しい限りです。EntityManager#migrateによって、Entityとテーブル構造が合わない場合にCreateTableやAlterTable のSQLを発行してくれます。これは、Ruby on Railsのmigrateと同じように使えるようです。データのInsertを行う部分は長くなるので省略してあります。最後にソースが公開してありますので、そちらを参照してください。

public class Main {
	public static void createTestData() throws SQLException {
		(省略
	}

	public static void main(String[] args) throws Exception {
		EntityManager manager = EntityManagerFactory.getInstance();
		manager.migrate(MUser.class, MUserGroup.class);

		if (false) createTestData();

		System.out.println("MUser Table count=" + manager.count(MUser.class));
		System.out.println("MUserGroup Table count=" + manager.count(MUserGroup.class));
		MUserGroup[] groups = manager.find(MUserGroup.class);
		for (MUserGroup group: groups) {
			System.out.println(group + ": " + group.getName());
			for (MUser user: group.getUsers()) {
				System.out.println("  " + user + ": " + user.getName());
			}
		}
	}
}

以上になります。

上記のソースは、Subversionにて http://taoe.jpn.ch:8080/svn/trunk/orm_compare/ActiveObjects から取得できます。良かったら自分で動かしてみてください*1

*1:PostgreSQLが必要になりますが^^;