CDIで複数データソースの切り替え
将来的にはJavaEEの仕様にマルチテナント機能が組み込まれますが、
僕は今のところ、複数データソースの切り替えが出来れば十分なので、
CDIを使ってやってみました。
これで1つのJavaEE6アプリで複数のデータベースへの接続を切り替える事が可能です。
では早速、実際のソースを見てみましょう。
まずはプロデューサ・メソッドから。
EntityManagerがDIされるフィードを複数持ち、プロデューサ・メソッドで何れかをreturnします。
今回の例ではシステム日付の秒で分岐しましたが、
実際はURLパラメータやCookieに保持した値などで分岐する事になると思います。
また、RequestScopedアノテーションを付けて、リクエスト毎に呼ばれるようにします。
public class EntityManagerFactory {
@PersistenceContext(unitName = "pu01")
private EntityManager em01;
@PersistenceContext(unitName = "pu02")
private EntityManager em02;
@RequestScoped
@Produces
@EntityManagerQualifier
public EntityManager getEntityManager() {
// システム日付が偶数秒ならem01に接続する。
DateTime dt = new DateTime();
int sec = Integer.parseInt(dt.toString("s"));
if (sec % 2 == 0) {
return em01;
} else {
return em02;
}
}
}
次にDIでEntityManagerを受け取る側
DIで受け取ったEntityManagerを使うだけです。
今回の例ではコントローラに書いてます。
@Model
public class SampleController {
@Inject
@EntityManagerQualifier
private EntityManager em;
public String getName() {
Query query = em.createNamedQuery("findAll", Sample.class);
return ((Sample) query.getSingleResult()).getName();
}
}
EntityManagerQualifierアノテーションはQualifier(限定子)です。
インジェクションの対象を限定(紐付け?)させています。
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface EntityManagerQualifier {
}
ソースはGitHubにアップしてます。
READMEに環境構築の手順メモも書いてます。
サンプルソース
以上、久々のJavaネタでした!