Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails Domain Classes in Sets

Is it a bad practice to use domain objects in Sets or as keys in Maps?

In the past I've done things like this a lot

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

However I have noticed that I often encounter problems when findAllByAuthorLike might return a list of Hibernate Proxy objects com.me.Book_$$_javassist_128 but findByTitleLike will return a proper com.me.Book object. This causes duplicates in the set because the real object and the proxy are considered not equal.

I find I need to be extremely careful when using Sets of domain objects like this, and I get the feeling it might be something I should not be doing in the first place.

The alternative is of course to use a set/map of id's, but it makes my code verbose and prone to misunderstanding

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

@Burt: I thought Grails domain classes already did this, at least so that equals/compare was done on class/id's rather than the object instance. Do you mean a special comparator for hibernate proxies?

return (this.class == obj.class && this.id == obj.id) || 
       (obj.class  == someHibernateProxy && this.id == obj.id)
like image 822
Akusete Avatar asked Jun 09 '11 02:06

Akusete


1 Answers

It's not bad practice at all, but just like in a non-Grails application you should override equals and hashCode if you'll be putting them in hash-based collections (HashSet, HashMap, etc.) and also implement Comparable (which implies a compareTo method) if you're going to use TreeSet/TreeMap/etc.

like image 159
Burt Beckwith Avatar answered Oct 12 '22 02:10

Burt Beckwith