複合主キーの対策
複合主キーの特徴と対策
主にサロゲートキーと一緒に話題になることの多いものです。 DBFluteではサロゲートキーで複合主キーを排除することが推奨されています。
ただし、それでも現実には複合主キーと対面することは多いものです。特に DBFlute は、既に運用しているシステムでDB変更が多くて、メンテナンスが大変なのでDBFluteに切り替える、ということでレガシーシステムにも採用されることが珍しくありません。
DBFluteでは、複合主キーによるフレームワークのサービスの低下を最小限食い止めるようにしています。
複合主キーによる機能制限
そもそも、どのような機能に制限が出るのか、以下の通りです。
- InScopeRelation が利用できない
- (Specify)DerivedReferrer が利用できない
- (Query)DerivedReferrer が利用できない
- NotExistsReferrer が利用できない (ExistsReferrer は可)
- ScalarCondition が利用できない
- シーケンスを使った Entity へのPK値の自動設定が利用できない
- QueryUpdate が利用できない
- QueryDelete が利用できない
主には、サブクエリ(特にInScopeのサブクエリ)を使って実現する機能が軒並み利用できなくなります。 もっと実装コストを掛ければ対応できそうなものもあれば、相当の実装コストを掛けても実現が難しいものもあります。
複合主キーへのできるだけの対応
それでも、できるだけの対応をしています。
- 結合条件の自動付与
- これは、SQLの自動組み立てのできるO/Rマッパではほとんど当たり前のことですが、ConditionBean では結合条件は単一であろうが複合であろうが意識せずに実装できます。結合条件における条件落ちを防ぐことができます。
- 相関サブクエリ条件の自動付与
- 複合主キーでも ExistsReferrer が利用できます。もともとできなかったものですが、よく使われる機能なので対応しています。 相関サブクエリ条件における条件落ちを防ぐことができます。ただし、同様に相関サブクエリで実現する NotExistsReferrer や DerivedReferrer は対応できていません。
- LoadReferrer の対応
- こちらも、もともとできなかったものですが、よく使われる機能なので対応しています。
- PK抽象化メソッド
- ConditionBean や Behavior には、幾つかのPK抽象化メソッドをがあります。ConditionBean の cb.addOrderBy_PK_Asc() cb.acceptPrimaryKey(pk) や Behavior の selectByPKValue() や cb.acceptPrimaryKey()、Behavior の selectByPKValue() などです。PKの条件落ちのバグなどを比較的抑えやすい機能です。
dbflute-multipledb-seasar-example にて、Example があります。
複合主キー対応のジレンマ
フレームワークとしては、こういった推奨されない環境(少なくとものそのフレームワークでは)に対する対応をどこまでするのか、常にジレンマがあります。 複合主キー対応は、フレームワーク開発における意識の矛盾の代表的な例です。
- DBFluteを利用することによる別のレイヤへの制限を(できるだけ)発生させたくない
- DBFluteで対応してるからって、何も考えずに複合主キーを許容してもらいたくない
この二つは常に対立します。また、複合主キーの問題に限りません。
幸い DBFlute は自動生成ツール一体型なので、比較的柔軟性があります。とりあえずはデフォルトでは推奨される方式を優先した仕様にし、 オプションで非推奨の環境にも対応できる、という形を心がけています。(もちろん、全てがそういうわけではありませんが)