7

セットでドメインオブジェクトを使用するのは悪い習慣ですか、それともマップでキーとして使用するのは悪い習慣ですか?

過去に私はこのようなことをたくさんしました

Set<Book> someBooks = [] as Set
someBooks.addAll (Book.findAllByAuthorLike('%hofstadter%'))
someBooks.add (Book.findByTitleLike ('%eternal%'))

findAllByAuthorLikeただし、Hibernate Proxyオブジェクトのリストを返す可能性com.me.Book_$$_javassist_128があるfindByTitleLikeが、適切なオブジェクトを返す場合に問題が発生することがよくありcom.me.Bookます。これにより、実際のオブジェクトとプロキシが等しくないと見なされるため、セット内で重複が発生します。

このようなドメインオブジェクトのセットを使用するときは、細心の注意を払う必要があると思います。そもそも、それは私がすべきではないことかもしれないと感じています。

もちろん、別の方法はIDのセット/マップを使用することですが、コードが冗長になり、誤解されやすくなります。

Set<Integer> someBooks = [] as Set // a set of id's for books    

@Burt:少なくともオブジェクトインスタンスではなくclass /idでequals/compareが実行されるように、Grailsドメインクラスはすでにこれを実行していると思いました。休止状態のプロキシ用の特別なコンパレータを意味しますか?

return (this.class == obj.class && this.id == obj.id) || 
       (obj.class  == someHibernateProxy && this.id == obj.id)
4

2 に答える 2

9

まったく悪い習慣ではありませんが、Grails 以外のアプリケーションと同じようにオーバーライドする必要がequalsありhashCodeます。/ /etcを使用します。HashSetHashMapComparablecompareToTreeSetTreeMap

于 2011-06-09T03:09:54.290 に答える
2

Hibernate に支えられた状況で equals() と hashcode() を適切に実装することは、簡単なことではありません。Java コレクションでは、オブジェクトのハッシュコードと equals() の動作が変更されないようにする必要がありますが、オブジェクトが新しく作成されたときにオブジェクトの ID が変更される可能性があり、さまざまな理由で他のフィールドが変更される可能性があります。変更不可能なビジネス ID を使用できる場合もありますが、そうではない場合がほとんどです。また、明らかにデフォルトの Java の動作も、Hibernate の状況には適していません。

私が見た最良の解決策は、次のとおりです。

それが説明する解決策は次のとおりです。オブジェクトが作成されるとすぐにIDを初期化します。Hibernate が ID を割り当てるのを待たないでください。バージョンを使用して新しいオブジェクトかどうかを判断するように Hibernate を構成します。このように、id は変更不可であり、hashcode() および equals() に安全に使用できます。

于 2011-08-24T11:06:33.237 に答える