2012-02-24 16 views
5

私はDDDについてEric Evansの本を読んでいます。私は次の引用に疑問があります。属性を使用しない場合は、どうすればequals()メソッドを作成しますか?私はJPAを使用していますが、固有のid属性を持っていますが、実際にエンティティを永続させるまでは設定されていません。あなたは何をしていますか?私は属性に基づいてequalsメソッドを実装しています。なぜなら、それは私のプロジェクトで失敗したからです。エンティティに関するドメイン駆動型設計のエンティティ

章:オブジェクトは、むしろその 属性よりも、そのIDによって区別される

は、モデル内の定義にこのプライマリを作ります。 のクラス定義はシンプルで、ライフサイクルの継続性と、 のIDに集中してください。 のフォームまたは履歴に関係なく、各オブジェクトを区別する手段を定義します。属性によって オブジェクトを一致させる必要がある要件に注意してください。 が各オブジェクトに対してユニークな結果を生成することが保証されている操作を定義します。 というシンボルが一意に保証されている可能性があります。この識別手段は、 が外部から来たものでもよく、 によって作成された任意の識別子であっても構わないが、モデル内の識別番号 に対応していなければならない。モデルは、同じことを意味するものを と定義しなければなりません。

http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215

+0

可能な複製、http://stackoverflow.com/questions/5031614/the-jpa-hashcode-equals-dilemma – MRalwasser

+0

idは私のために正常に動作します参照してください。http://stackoverflow.com/questions/7579404 /使用して自動生成されたIDのハイバネーションエンティティオブジェクトと同等のハッシュコードのオブジェクト – NimChimpsky

答えて

1

カップルは、可能なアプローチ:

  • は、ビジネスキーを使用してください。これは最も「DDDに準拠した」アプローチです。ドメインとビジネス要件を詳しく見てください。あなたのビジネスは顧客をどのように特定していますか?彼らは社会保障番号または電話番号を使用していますか?紙ベースのコンピュータ(コンピュータなし)の場合、この問題はどのように解決されますか?自然なビジネスキーがない場合は、サロゲートを作成します。最終的なビジネスキーを選択し、equals()で使用します。この特定の問題に特化したDDD本のセクションがあります。

  • 自然なビジネスキーがない場合は、UUIDを生成できます。これは、分散システムでも利点があります。その場合、新しいIDを生成するためにデータベースのような集中型(および潜在的に利用不可能な)リソースに頼る必要はありません。

  • エンティティクラスのデフォルト値equals()に依存するオプションもあります。2つのメモリ位置を比較すると、Unit Of Work(Hibernate Session)がすべてのエンティティ(このORMパターンはIdentity Mapと呼ばれます)に保持されるため、ほとんどの場合、これで十分です。それはあなたが1 HibernateのSession(スレッド、切り離されたエンティティなどを考える)

  • 興味深いことに

の範囲に限定されるものではなく、エンティティを使用する場合、「公式」DDDサンプルは非常にを使用して解除されますので、これは信頼できるものではありませんすべてのエンティティクラスを1つの方法でEntityインターフェイスから派生した軽量フレームワーク:属性namesurname

boolean sameIdentityAs(T other) 
// Entities compare by identity, not by attributes. 
+0

エンティティが質問だったとしましょう。私は何を使うでしょうか?私は今まで生成されたIDに頼ってきました。 – LuckyLuke

+0

あなたのドメインに依存しますが、おそらく質問自体のテキスト(その場合はValue not Entity)ですが、質問番号のようなものでしょう。本当にあなたのドメインに依存します。 – Dmitry

1

オブジェクトはまだ永続的でない場合は、その属性に基づいて、2つのオブジェクトを比較する上で害はありますか?

あなたのプロジェクトでこれがなぜ失敗したのか分かりませんが、私の経験上、属性に基づく比較は、属性が最終的でない場合、ほとんどの場合常に滑りやすい傾向にあります。つまり、現在等しい2つのオブジェクトは、いつか後で等しくない可能性があります。これは非常に悪いです。

ほとんどのJavaクラスはアクセサーとともに書かれているため、属性を比較することは悪い考えです。

しかし、IDフィールドがnullでないかどうかを最初に確認することになります。それがnullの場合、属性の比較に戻ります。それがヌルでない場合は、それを使用して何もしません。これは理にかなっていますか?

+2

これは危険なことです。 IDを割り当てる前にオブジェクトをHashSetに格納すると、HashSetが破損します。 –

+0

確かに。しかし、その後、私はidを取得するためにオブジェクトを永続させると仮定します。その場合、私は一般的に返される永続オブジェクトを取得して使用する方が好きです。基本的には、等価チェックで使用されるオブジェクトの状態を変更しないでください。 – Pavan

+0

オブジェクトの属性に基づいてオブジェクトを比較すると、エンティティではなく値オブジェクトとして動作しています。値オブジェクトとエンティティはDDDで全く異なるセマンティクスを持つため、エンティティの等価性を属性に基づいてはいけません。 –

1

考えるPersonクラス。 21歳の人が名前を変更するとき、それはまだ同じPersonです(等しいはtrueとなります)? 属性に等号を書き込むと、同じ人ではないので、私の意見では、最も良いアプローチは、ビジネス識別子(エンティティライフサイクル全体にわたって一意かつ不変)でエンティティの平等をテストすることです。

0

もう1つの解決方法は、エンティティにUUIDフィールドを使用することです。

この場合、UUIDをプライマリキーとして使用するか、または同等のものとして使用できます。

@Entity 
public class YourEntity{ 

    @Id 
    private String uuid = UUID.randomUUID().toString(); 

    // getter only... 

} 
関連する問題