Announcement Announcement Module
Collapse
No announcement yet.
Can AOP help me with boiler plate equals() & hashCode() methods Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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...

    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

    Comment


    • #3
      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);
      	}
      
      }

      Comment


      • #4
        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.

        Comment


        • #5
          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

          Comment


          • #6
            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

            Comment


            • #7
              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, 04:10 AM.

              Comment


              • #8
                @ 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 2nd, 2006, 12:15 AM.

                Comment


                • #9
                  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.

                  Comment


                  • #10
                    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.

                    Comment


                    • #11
                      Originally posted by Arno Werr
                      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.
                      Just the normal xml based hibernate mapping files.

                      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.
                      Why is that bad? I love it when I can see the complete mapping behaviour of an entity in a single file. Maybe the XML isn't the best solution, but seperating the core aspects from the mapping aspects imho is a good thing.

                      Java + XDoclet/JEE annotations is my way of doing things in domain objects area.
                      That is your choice.

                      But I followed your link, poked around and what I see. You actually has So, you dislike annotations
                      I don't dislike annotations. But using annotations for adding every kind of metadats is a bad thing. In some cases annotations are good, in some cases external metadata is good.

                      and you dislike XML.
                      Nope.. I don't dislike XML. I just don't like it when it is used for every kind of domain specific language.

                      Instead you are advancing some kinda proprietary Java-based API
                      ( http://forum.springframework.org/showthread.php?t=17691 ). (Oh, man, yet another API...)
                      API != Syntax.

                      Nah... I really hate the idea of recompiling my codebase whenever I need to swap implementations of my DAO.
                      I don't think you get it. The choice between an XML based syntax or a custom one, doesn't influence this proces. So there is no need to recompile.

                      XML allows me doing things without touching my Java codebase, so I'd rather stick with XML.
                      The same goes for a custom syntax.

                      The main advantage of XML is that most modern ide's have support for it: just need to import a dtd or a schema file, and you have autocompletion in your editor. This is much more difficult for a custom syntax.

                      Comment

                      Working...
                      X