Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Can AOP help me with boiler plate equals() & hashCode() methods

  1. #1
    Join Date
    Jan 2006
    Location
    Sydney, Australia
    Posts
    14

    Smile Can AOP help me with boiler plate equals() & hashCode() methods

    AOP newbie question.

    Having spent the afternoon cleaning up equals() and hashCode() methods, I'm looking for a better way to do things.

    Can AOP help with the mudane task of implementing these methods?

    Could an annotation be used to flag fields that I wish to included in the evaluatation of equals() and hashCode() methods?
    Is this possible? Would it be a bad idea to wrap my domain model in proxied equals() and hashCode() methods? What do people think?

  2. #2
    Join Date
    Aug 2004
    Posts
    2,715

    Default

    Quote Originally Posted by crbaker
    Could an annotation be used to flag fields that I wish to included in the evaluatation of equals() and hashCode() methods?
    I think so, but...

    Quote Originally Posted by crbaker
    Would it be a bad idea to wrap my domain model in proxied equals() and hashCode() methods? What do people think?
    I would not recommend this. Unless you always use AspectJ your proxies are effectively delegates to the real objects. Therefore you always have to ensure that different objects refer to each other solely via a proxy in order to be sure that equals and hashCode would work correctly.

    Besides that: equality of domain objects is defined in means of the domain they belong to. So the equals() method has a domain-specific meaning and there would be no sense in factoring this responsibility out of the object.

    The hashCode() method is more technically oriented. But anyway it would not improve maintenance to separate the implementation of these two methods.

    So to make it short: I would always implement these methods inplace.

    Regards,
    Andreas

  3. #3
    Join Date
    Dec 2005
    Location
    U-241
    Posts
    237

    Default

    I am using not AOP but rather Apache HashCodeBuilder and EqualsBulder
    Code:
    import org.apache.commons.lang.builder.EqualsBuilder;
    import org.apache.commons.lang.builder.HashCodeBuilder;
    
    @MappedSuperclass
    public abstract class BaseEntity implements Serializable {
    	private static final long serialVersionUID = 1353453L;
    
    	@Id
    	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hibernate3_sequence")
    	private Long id;
    
    	@Version
    	@Temporal(TemporalType.TIMESTAMP)
    	@Column(name = "last_update")
    	private Date lastUpdate;
    
    	public Long getId() {
    		return id;
    	}
    
    	protected String getHashCodeId() {
    		if (1 == 1) {
    			throw new IllegalStateException("You must override this method");
    		}
    		return getId() == null ? getNumber().getFullPhoneNumber().toString() : getId().toString();
    	}
    
    	public int hashCode() {
    		if (1 == 1) {
    			throw new IllegalStateException("You must override this method");
    		}
    		return new HashCodeBuilder(13, 37).append(getHashCodeId()).toHashCode();
    	}
    
    	public boolean equals(Object o) {
    		return EqualsBuilder.reflectionEquals(this, o);
    	}
    
    }
    Spring, it's a wonderful thing...

  4. #4
    Join Date
    Jan 2006
    Location
    Sydney, Australia
    Posts
    14

    Default

    Thanks for you thoughts, seems like AOP for equals() and hashCode() might not be the smartest choice.

    I'm trying to avoid commons EqualsBuilder and HashCodeBuilder as the system has soon steep performance requirements, and while I haven't independently tested the overhead of these helper classes, I guessing the object creation will added up over thousands of evaluations.

    I like the idea of forcing implementation of hashCode() and equals() on all sub classes of AbstractEntity, I might borrow this for my AbstractEntity object stack.

    Cheers,

    Craig.

  5. #5
    Join Date
    Dec 2005
    Location
    U-241
    Posts
    237

    Default

    Glad you liked it.
    I'm trying to avoid commons EqualsBuilder and HashCodeBuilder as the system has soon steep performance requirements, and while I haven't independently tested the overhead of these helper classes, I guessing the object creation will added up over thousands of evaluations.
    I personally don't really mind. If I need thousands of evaluations in one transaction I wouldn't use ORM anyways. Straight to DB and execute stored procedure. If thousands evaluations stretched over weekend , heck, so be it. If I see that some collection, say in cache, drags me down, I'll go and reimplement hashCode() and equals (most often actually) on that particular domain object in the offending collection. Well, I am not dealing with NASA. My customers are more in line with Uncle Joe Convenience Store web site.

    Cheers,
    Arno
    Spring, it's a wonderful thing...

  6. #6
    Join Date
    Aug 2004
    Posts
    2,715

    Default

    As you prefer manual implementation (as I do, too) I want to recommend you this link. Besides general things concerning equals() and hashCode() it also provides some implementation hints, in case you do not already know.

    Hope that helps,
    Andreas

  7. #7
    Join Date
    Nov 2004
    Location
    Hilversum - The Netherlands
    Posts
    1,054

    Default

    Quote Originally Posted by Arno Werr
    I am using not AOP but rather Apache HashCodeBuilder and EqualsBulder
    1) the annotations are hurting my eyes.
    2) the hashcode is not correct (because it isn't constant). I bet the same goes for the equals.

    Personally I never liked the Hash and Equal builders.

    ps:
    try to realize what is going to happen when you have two different instances of the same object in the same 'isolated object space' (it could be all the objects within a single transaction).

    If there are two different instances of the same object in the same 'isolated object space', something has gone terribly wrong (it could happen that some actions are taken on one instance, and other actions on the other instance -> your system is fucked). That is why hashcode and equals in most cases don't have to be implemented (imho) on domain objects because you don't want to have multiple instances of the same entity. So the original equals and hashcode of the object will do perfectly (if objects are isolated and not shared between transactions/threads).

    Hibernate: equals and hashcode
    Last edited by Alarmnummer; Sep 1st, 2006 at 03:10 AM.

  8. #8
    Join Date
    Dec 2005
    Location
    U-241
    Posts
    237

    Default

    @ Andreas Senft
    Thank you, Andreas, for the link. I am using builders as 'simplest thing that possibly work' implementation. Should there be a problem it is easy to fix using solutions mentioned in the link provided.
    @Alarmnummer
    the annotations are hurting my eyes.
    Yeah, I have a medical condition too. I usually feel seek and like I gonna puke whenever some guys would say 'sure, we have domain model' and show me a bunch of config files *.hbm.xml.
    the hashcode is not correct (because it isn't constant)
    Really do not see a practical problem here. Care to elaborate where is the beef? I might be wrong...
    ps: So the original equals and hashcode of the object will do perfectly (if objects are isolated and not shared between transactions/threads).
    I do agree with you. Actually, there is no revelation in it. As C.Bauer&G.King put it
    it’s possible to build a complex application with identity
    (default) equals as long as you exercise discipline when dealing with detached
    objects from different sessions (and keep an eye on serialization and deserialization).
    One nice thing about this approach is that you don’t have to write extra code
    to implement your own notion of equality.
    p. 122
    And then - about component!!! classes
    Strictly speaking, implementing equals() and hashCode() isn’t required for all component classes. However, we recommend it for any component class because the implementation is straightforward and “better safe than sorry” is a good motto.
    Hibernate in Action
    p.217
    Safe or sorry. It's a judgment call. Right?
    Last edited by Arno Werr; Sep 1st, 2006 at 11:15 PM.
    Spring, it's a wonderful thing...

  9. #9
    Join Date
    Nov 2004
    Location
    Hilversum - The Netherlands
    Posts
    1,054

    Default

    Quote Originally Posted by Arno Werr
    @ Andreas Senft
    @Alarmnummer

    Yeah, I have a medical condition too. I usually feel seek and like I gonna puke whenever some guys would say 'sure, we have domain model' and show me a bunch of config files *.hbm.xml.
    I don't get your point.

    And placing all metadata (annotations) in domain objects imho is not that great. check out the following blog for a good example how it can lead to painfull code.

    Dude where is my class

    Really do not see a practical problem here. Care to elaborate where is the beef? I might be wrong...
    At has to do with the fact that the hashcode is not constant. Check out effective Java or the javadoc for more information about the problem. You also could check the following post Hibernate equals and hash

    Safe or sorry. It's a judgment call. Right?
    Nope.. it's a bug.. nothing more and nothing less. has nothing to do with taste.

  10. #10
    Join Date
    Dec 2005
    Location
    U-241
    Posts
    237

    Default

    Quote Originally Posted by Alarmnummer
    I don't get your point.
    My point? OK. You dislike annotations. Yet we have to configure somehow our domain class. What other options do we have? *.properties files? I couldn't assume you would back up this proposition for an enterprise application. Than what? XML? XML is a great technology and I love it but as anything in this world it can be used and abused (the same goes with annotations, of cause). Example of improper usage of XML - *.hbm.xml for definition and configuration of domain classes embraced by Hibernate newbies. Java + XDoclet/JEE annotations is my way of doing things in domain objects area. But I followed your link, poked around and what I see. You actually has
    a dislike for XML. It isn`t that I hate XML, but it can be quite verbose and I have the feeling XML is used for the wrong reasons in a lot of cases.
    So, you dislike annotations and you dislike XML. Instead you are advancing some kinda proprietary Java-based API
    ( http://forum.springframework.org/showthread.php?t=17691 ). (Oh, man, yet another API...) Nah... I really hate the idea of recompiling my codebase whenever I need to swap implementations of my DAO. XML allows me doing things without touching my Java codebase, so I'd rather stick with XML.
    Spring, it's a wonderful thing...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •