DBFluteで親テーブルをキャッシュから取得するサンプル

DBFlute-0.9.9.1B から、Entityの親テーブルがnullの場合に、代わりとなるインスタンスを返すことができるようになりました。この仕組みを使うことで、頻繁に結合されるテーブル(マスタなど)を、毎回DBアクセスせずにキャッシュから取得させることができます。DBFluteの設定方法とキャッシュの実装サンプルをGithubに上げたついでに、ちょっと解説します。

普通のDBFlute

普通のDBFluteで、関連テーブルも一緒に取得するには、ConditionBeanのSetupSelectを使います。こんな感じですね。

MemberCB cb = new MemberCB();
cb.setupSelect_MemberStatus();
cb.query.setMemberId_Equal(1);
Member member = memberBhv.selectEntity(cb);

こうすることで、member.getMemberStatus() で MemberStatus インスタンスを取得できます。cb.setupSelect_MemberStatus() を呼び出さなかった場合、member.getMemberStatus() はnullを返します。

relationalNullObjectMap の設定

member.getMemberStatus() がnullを返すとき、代わりにキャッシュからインスタンスを取得させるようにします。それには、littleAdjustmentMap.dfprop の relationalNullObjectMap を設定します。該当するコミットはこちら

; relationalNullObjectMap = map:{
    ; providerPackage = com.github.taktos.dbflute.cache
    ; foreignMap = map:{
        ; MEMBER_STATUS = MemberStatusCache.get($$PrimaryKey$$)
    }
}

foreignMap の MEMBER_STATUS は、テーブル名です。MEMBER_STATUSへの外部キーを持つテーブルのEntityすべてに設定が効きます。MemberStatusCache.get($$PrimaryKey$$) が、関連テーブルがnullのとき代わりに実行されるコードになります。providerPackage はimport文に追加されます(多分)。ので、MemberStatusCacheをFQDNで書いたら不要(多分)。


設定を追加してDBFluteでコード生成しなおすと、BsEntityの関連テーブル取得メソッドが以下のように変わります。

 public MemberStatus getMemberStatus() {
+    if (_memberStatus == null) {
+        _memberStatus = MemberStatusCache.get(getMemberStatusCode());
+    }
     return _memberStatus;
 }

MEMBER_STATUSテーブルのインスタンスがnullかチェックし、nullの場合は代わりのコードを実行するようになりました。

なお、キャッシュの仕組みは自前で用意する必要がありますので、都合に応じて作ってください。(Githubに上げたサンプルは、staticイニシャライザでキャッシュしたインスタンスを返す簡単な実装しかしていません。)