ActiveObjectsを使ってみた(2) - PostgreSQL

ActiveObjectsを使ってみた(1)ではMySQLを使いましたが、同じプログラムをPosgreSQLでも動かしてみました。
今回修正が必要な個所は3点のみでした。

  • EntityManagerの生成時に渡すURL/ユーザ名/パスワード
  • マイグレーション時のクラスパスに含めるJDBCドライバ
  • Webアプリケーションのクラスパスに含めるJDBCドライバ

なお、コンパイル時のクラスパスにJDBCドライバは不要です。

その前にリファクタリング

上記で3点といったもの、実際にはEntityManagerの生成箇所は複数あります。しかし、そもそもEntityManagerを複数個所で生成するのはおかしいので、一つのクラスにまとめました。
ここで、おかしいと言っているのは、

EntityManager is designed to be used in an instance fashion with each instance corresponding to a single database.

EntityManagerは一つのインスタンスを一つのデータベースに対応させて使用するように設計されています。

に反し、同じデータベースに対応する複数のEntityMangaerインスタンスを生成している点です。複数個所で生成すると(おそらく)キャッシュの整合性も取れなくなるとおもいます。
以下、今回追加したシングルトンクラスです。

SingletonEntityManager
package sample;

import net.java.ao.EntityManager;

public final class SingletonEntityManager {
	private static EntityManager manager = new EntityManager( "jdbc:mysql://localhost/sample", "root", "root" );
	
	private SingletonEntityManager() {}
	
	public static EntityManager getInstance() {
		return manager;
	}
}

今までEntityManagerを生成していた個所は、すべて「SingletonEntityManager.getInstance()」に置き換えます。こうすることで、EntityManagerの生成箇所はSingleTonEntityManager一か所になります。なおかつ、EntityManagerのインスタンスの生成はSingletonEntityManagerの生成のタイミングだけになります。

(でも、Servletでシングルトンクラス作ってもダメなんじゃなかろうか・・・?SingletonEntityManagerクラスがアンロードされると、EntityManagerを再度生成することになってしまうと思う。この問題については後で考える)

EntityManagerの生成時のURL/ユーザ名/パスワード

上記のSingletonEntityManager中のEntityManager生成時の引数を変更します。

MySQL
new EntityManager( "jdbc:mysql://localhost/sample", "root", "root" );
PostgreSQL
new EntityManager( "jdbc:postgresql:sample", "postgres", "postgres" );

マイグレーション時のクラスパスに含めるJDBCドライバ

javaコマンド発行時のクラスパスに、postgreSQLJDBCドライバを含めます。

MySQL
java -classpath sample\WEB-INF\classes;sample\WEB-INF\lib\activeobjects-0.8.2.jar;sample\WEB-INF\lib\mysql-connector-java-5.1.0-bin.jar sample.Driver
PostgreSQL
java -classpath sample\WEB-INF\classes;sample\WEB-INF\lib\activeobjects-0.8.2.jar;sample\WEB-INF\lib\postgresql-8.3-604.jdbc4.jar sample.Driver

Webアプリケーションのクラスパスに含めるJDBCドライバ

warのWEB-INF/libフォルダに、postgreSQLJDBCドライバを配置します。

実行してみた!

mysqlの場合とまったく同じ動きをしているように見えます。
画面イメージは、ActiveObjectsを使ってみた(1)をご覧ください。

それぞれのDBでのテーブル定義

単品商品(SingleProduct)エンティティからマイグレーションした、それぞれのDBでのテーブル定義を示します。

MySQL
mysql> desc singleproduct;
+-----------+--------------+------+-----+---------------------+----------------+
| Field     | Type         | Null | Key | Default             | Extra          |
+-----------+--------------+------+-----+---------------------+----------------+
| id        | int(11)      | NO   | PRI | NULL                | auto_increment |
| name      | varchar(255) | YES  |     | NULL                |                |
| productNo | int(11)      | NO   | UNI |                     |                |
| saleFrom  | timestamp    | NO   |     | CURRENT_TIMESTAMP   |                |
| saleTo    | timestamp    | NO   |     | 0000-00-00 00:00:00 |                |
| price     | bigint(20)   | YES  |     | NULL                |                |
+-----------+--------------+------+-----+---------------------+----------------+
6 rows in set (0.07 sec)
PostgreSQL
sample=# \d singleproduct
                                     Table "public.singleproduct"
  Column   |            Type             |                         Modifiers
-----------+-----------------------------+------------------------------------------------------------
 id        | integer                     | not null default nextval('singleproduct_id_seq'::regclass)
 name      | character varying(255)      |
 productno | integer                     | not null
 salefrom  | timestamp without time zone |
 saleto    | timestamp without time zone |
 price     | bigint                      |
Indexes:
    "singleproduct_pkey" PRIMARY KEY, btree (id)
    "singleproduct_productno_key" UNIQUE, btree (productno)

おわりに

ここまで、業務ロジック部分は全くいじりませんでした。EntityManagerの引数とJDBCドライバを変えるだけで、DBの切り替えが可能でした。ActiveObjectsさすがですね!