IDとしてのドメインオブジェクトは、いくつかの複雑で微妙な問題を引き起こします。
シリアライゼーション/デシリアライゼーション
オブジェクトをキーとして保存すると、オブジェクトグラフのシリアル化が非常に複雑になります。stackoverflow再帰のために、JSONまたはXMLへの単純なシリアル化を実行すると、エラーが発生します。次に、オブジェクトインスタンスをシリアル化して再帰を作成する代わりに、実際のオブジェクトをIDを使用するように変換するカスタムシリアライザーを作成する必要があります。
型の安全性のためにオブジェクトを渡しますが、IDのみを保存します。これにより、呼び出されたときに関連エンティティを遅延ロードするアクセサーメソッドを使用できます。2番目のレベルのキャッシュは、後続の呼び出しを処理します。
微妙な参照リーク:
存在するようなコンストラクターでドメインオブジェクトを使用すると、アクティブに使用されていないオブジェクトのメモリを回収することを非常に困難にする循環参照が作成されます。
理想的な状況:
不透明なIDとint / long:
idそれは識別するものについて何の情報も運ばない完全に不透明識別子でなければなりません。ただし、システムで有効な識別子であることを確認する必要があります。
生の型はこれを壊します:
int、longおよびStringRDBMSシステムで識別子に最も一般的に使用されるrawタイプです。数十年前の実用的な理由には長い歴史があり、それらはすべて、節約spaceまたは節約、timeあるいはその両方に当てはまる妥協案です。
シーケンシャルIDは最悪の違反者です。
シーケンシャルIDを使用すると、デフォルトで一時的な意味情報がIDにパックされます。それは使用されるまで悪くありません。IDのセマンティック品質をソートまたはフィルタリングするビジネスロジックの作成を始めると、将来のメンテナーに苦痛の世界をもたらします。
String 素朴なデザイナーは情報をコンテンツにパックするため、フィールドには問題があります。通常は時間的セマンティクスも含まれます。
これらはグローバルに一意で12437379123はないため、分散データシステムを作成することも不可能です。分散システムの別のノードが同じ番号のレコードを作成する可能性は、システムで十分なデータを取得したときにほぼ保証されます。
その後、ハックがそれを回避し始め、すべてが蒸し混乱の山に展開します。
巨大な分散システム(クラスター)を無視すると、他のシステムとデータを共有しようとするときに完全な悪夢になります。特に、他のシステムが管理できない場合。
あなたはまったく同じ問題、つまりあなたのIDをグローバルにユニークにする方法で終わります。
UUIDが作成され、次の理由で標準化されました:
UUIDVersion使用する方法によっては、上記のすべての問題が発生する可能性があります。
Version 1MACアドレスと時間を使用して、一意のIDを作成します。これは、場所と時間に関するセマンティック情報を含んでいるため、悪いです。それ自体は問題ではなく、単純な開発者がビジネスロジックのためにその情報に依存し始めるときです。これにより、侵入の試みで悪用される可能性のある情報も漏洩します。
Version 2ユーザーUIDまたはGIDand domianを使用するか、UIDまたはこれGUIからの時間の代わりにこれを使用すると、データ漏洩とVersion 1同じくらい悪いVersion 1情報であり、この情報がビジネスロジックで使用されるリスクがあります。
Version 3似ていますが、MACアドレスと時間を、意味的に意味のあるものからのMD5配列のハッシュに置き換えbyte[]ます。気になるデータ漏えいはなく、byte[]からの復旧はできませんUUID。これにより、UUIDインスタンスフォームとある種の外部キーを確定的に作成することができます。
Version 4 良い解決策である乱数のみに基づいており、意味論的な情報はまったくありませんが、確定的に再作成することはできません。
Version 5と同じですVersion 4が、のsha1代わりに使用しますmd5。
ドメインキーとトランザクションデータキー
ドメインオブジェクトIDの私の好みは、使用するVersion 5かVersion 3、Version 5技術的な理由で使用が制限されている場合です。
Version 3 多くのマシンに分散する可能性のあるトランザクションデータに最適です。
スペースの制約がない限り、UUIDを使用します。
それらは一意であることが保証されており、1つのデータベースからデータをダンプし、別のデータベースにリロードすると、実際に異なるドメインデータを参照する重複IDについて心配する必要がありませんでした。
Version 3,4,5 完全に不透明であり、本来あるべき姿です。
1つの列を主キーとしてa UUIDを使用して、自然な複合主キーとなるものに対して複合一意インデックスを作成できます。
ストレージもそうである必要はありませんCHAR(36)。あなたは、保存することができUUID、長いそれはまだインデックス可能な限り与えられたデータベースのネイティブのバイト/ビット/番号フィールドに。
レガシー
raw型があり、それらを変更できない場合でも、コード内で抽象化できます。
a Version 3/5を使用するとUUID、Class.getName()+ String.valueOf(int)をaとして渡し、再作成byte[]可能で確定的な不透明な参照キーを持つことができます。