将来的には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ネタでした!
広告
2012/11/24 22:14
こんにちは、河野です。
これ、HttpServletRequestの内容によって処理を分岐させたい場合にどうやってHttpServletRequestオブジェクトを取得すればいいんでしょう?
FacesContextを使う方法はあるみたいですが、JSFに依存するのはなんかイヤな感じなので・・・
2012/11/25 01:21
河野さんこんばんは。コメントありがとうございます!
業務ではFacesContextでやってたのですが、確かにHttpServletRequestの方がいいですよね。
Seasar2みたいにMapがベストなんでしょうけど。
ソース直してGitHubにアップしてます。
そのままではHttpServletRequestがDI出来ませんでした。
プロデューサ・メソッドが必要みたいです。
https://github.com/matsumana/javaee6-multi-datasource-sample/commit/af5e94589b73891bb617a466d3fc3d660008402c