例から始めましょう:エンティティBook
があります。一意のIDがあります:Isbn
-String
をラップする値オブジェクト。これはUUIDです。
Book
エンティティには、リポ(sql db)からのサロゲートIDも必要です。私たちができるように、それが必要です。データベースは文字列よりも番号で検索するため、より高速に本を検索できます。
私が読んだことから、代理キーはBook
sインターフェイスから非表示にする必要があります。しかし、私たちはそれを使用して、より速く本を見つけることを望んでいます。
これを適切に処理する方法は?
[A]Book
にgetSurrogateId()
(またはより適切な名前)を追加するだけです。これはエンティティを汚染しますが、そのKISSを汚染します。
[B]自然なもののサロゲートキーを見つける責任を負うレポを持つことができます。たとえば、BookRepository
には次のメソッドがあります。
long toSurrogateKey(Isbn isbn) {
// lookup the cache
// if not found, lookup the db
}
代理キーを返すには-もちろん、これらの値はローカルにキャッシュできるため、毎回dbを検索する必要はありません。このメソッドはpublic
であってはなりません(右)?
[C]さらに進んで、代理キーをリポジトリ固有のキーと考えることができます。 Book
はインターフェイスであり、SqlBook
はリポジトリで作成された実装である場合があります。このSqlBook
実装は、リポジトリに必要なすべての追加情報を格納できます。この場合、サロゲートキーはSqlBook
のプロパティの1つとして保持されます-SqlBook
のユーザーはBook
、つまりサロゲートIDを認識していません。
したがって、上記のメソッドは次のようになります(SqlBook
クラスで定義):
long toSurrogateKey(Book book) {
return ((SqlBook)book).getSurrogateId();
}
ここでの唯一の欠点は、Book
(およびその他のエンティティ)がリポジトリ対応のファクトリによって作成される必要があることです。言い換えると、SqlFactory
sを作成するファクトリのSqlBook
実装が必要です。
これについて何か知恵はありますか?
私たちができるように、それが必要です。データベースは文字列よりも番号で高速に検索するため、より高速に本を検索できます。
サロゲートキーは、仮説的なパフォーマンスの問題ではなく、主キーを構築するための統一された方法を提供するため、主に追加する必要があります。それらは、外部キーとして誤用するため、モデルの半分以上が別々の場所に分散されるようなIsbnのようなビジネスデータを回避するのに役立ちます。
「私が読んだことによると、代理キーはBooksインターフェースから非表示にする必要があります」。
たぶん、この目的を誤解しているだけなのでしょうか?サロゲートキーは、ドメインの専門家とモデルについて話し合うときに非表示にする必要がある技術的な詳細ですが、モデルの実装に対する視点を変更するときにそれらを確認しても問題ありません。したがって、[A]を使用しますが、getSurrogateId()
アクセサーがドメインモデルのグラフィック形式で表示されないようにします。