Announcement Announcement Module
Collapse
No announcement yet.
How do you do with id concerning hashCode() and equals()? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How do you do with id concerning hashCode() and equals()?

    I have read and taken part in this discussion: <http://www.hibernate.org/109.html> which didn't really come up with any "patent-solution". So I thought that maybee you guys hanging around here might have some answers. The main problem is that you can't generate a hashcode using the values of the objects fields since they may change (when an object is edited) and thus breaks the equals / hashcode convention. I see three main solutions to this:
    1. Let equals and hashcode depend on the id. This means that if you use an id generated by the db you have to save the object to the database before you can use it in any set. (The id would change when saved to database) This sucks.
    2. Don't use the id in equals but only compare the fields and set the hashcode to 0. Now all hashSets more or less becomes linked lists. This sucks.
    3. My own desperate solution: When creating an object generate a random hashcode and persist it with the object. And don't use the id for equals because the id is 0 until the objects are stored when using the database for generating unique ids. This means that the database contains a nonunique random number for each item. This doesn't exactly suck but it sure ain't pretty.
    Can anyone suggest a better solution? I have heard about some ways to generate unique id's. Will these be Java longs or are they even more huge taking up alot of space? And do they work?

  • #2
    The last project I worked on used a combination of business key (e.g. social security number, username, etc...) and in cases where that didn't work some kind of UUID which was persisted.
    Last edited by karldmoore; Aug 29th, 2007, 11:53 AM.

    Comment


    • #3
      You need a business key as suggested. We have a code field which is unique to the entity, this makes the hashcode short and sweet. Combind this with some contraints/validators and it seems to hold up fine.

      Comment


      • #4
        Originally posted by jamesclinton View Post
        You need a business key as suggested. We have a code field which is unique to the entity, this makes the hashcode short and sweet. Combind this with some contraints/validators and it seems to hold up fine.
        Yes that would be the ideal solution but how do you know that the code field is unique? Or rather how do you generate that code? If the database is used for generating a unique code that means that the code is unspecified before the entity is saved to the database which means that the entity can't be put in a HashSet before being saved to the database...

        And if the business fields are used that would mean that the id and the hashcode would change when the entity is edited thus breaking the equals hashcode convention in regards to the HashSet.

        Comment


        • #5
          Originally posted by Jonathan Alvarsson View Post
          Yes that would be the ideal solution but how do you know that the code field is unique? Or rather how do you generate that code? If the database is used for generating a unique code that means that the code is unspecified before the entity is saved to the database which means that the entity can't be put in a HashSet before being saved to the database...

          And if the business fields are used that would mean that the id and the hashcode would change when the entity is edited thus breaking the equals hashcode convention in regards to the HashSet.
          That's easy As key is business then they are supplied by application and not by DB. And because it is key its editing shall be prohibited (as it editing means that from business point of view it is completely different object).

          REgards,
          Oleksandr

          Comment


          • #6
            Originally posted by al0 View Post
            That's easy As key is business then they are supplied by application and not by DB. And because it is key its editing shall be prohibited (as it editing means that from business point of view it is completely different object).

            REgards,
            Oleksandr
            Ah I see. But not all entities (more like just a few) have good businees keys. What to about the others?

            Comment


            • #7
              Originally posted by Jonathan Alvarsson View Post
              Ah I see. But not all entities (more like just a few) have good businees keys. What to about the others?
              In my experience, almost all entities have a business key good enough for life of a session And only this is important from hashcode point of view.

              And even if a business key is not so "good" and is editable it is Ok include it in hashcode calculation as far as is it is used in the equals().

              And for very "bad" objects, as last resort, you may supply IDs yourself (preferrably, on object creation), before object is stored to DB.

              Regards,
              Oleksandr

              Comment


              • #8
                Originally posted by al0 View Post
                In my experience, almost all entities have a business key good enough for life of a session And only this is important from hashcode point of view.
                Indeed, if there is literally nothing to use as the key, you do wonder if it's an entity at all. Is it tied to the lifecycle of another entity and actually some kind of component.

                Originally posted by al0 View Post
                And for very "bad" objects, as last resort, you may supply IDs yourself (preferrably, on object creation), before object is stored to DB.
                Absolutely, maybe if you have some concrete examples of the problems you are having it might make things clearer.
                Last edited by karldmoore; Aug 29th, 2007, 11:53 AM.

                Comment


                • #9
                  Originally posted by karldmoore View Post
                  Indeed, if there is literally nothing to use as the key, you do wonder if it's an entity at all. Is it tied to the lifecycle of another entity and actually some kind of component.
                  Hm I am not sure I follow this reasoning. An id that only is good for the lifetime of a session? How would I use that?

                  Originally posted by karldmoore View Post
                  Absolutely, maybe if you have some concrete examples of the problems you are having it might make things clearer.
                  If you have your entity in Persistant set it uses the hashcode to figure out which hashbucket to put the object in. If you change the object and the hashcode a contains() call probably return false since the new hashcode does not reference the old hashbucket. I also think that if equals have been changed the same thing happens since if more than one object is in a hashbucket equals is used to identify the sought after object. Hence fields that can change can not be used for equals and hashcode if you want to use the hashset as a hashset...

                  Comment


                  • #10
                    Originally posted by Jonathan Alvarsson View Post
                    Hm I am not sure I follow this reasoning. An id that only is good for the lifetime of a session? How would I use that?
                    Ok maybe I just confused this by thinking out loud, I really should stop doing that . In the past I've seen entities that didn't really have any unique identity (apart from the PK) and didn't really seem to be entities in the conventional sense. They were really just value objects tied to the lifecycle of the owning entity. When it was created/deleted so was this, e.g. a User has a Collection of attributes which can contain many values. The attribute itself has a potential key in the attributeName, the values of the attribute however don't. That was the kind of situation I was thinking of. In this sense the attribute values aren't really entities at all it's just a Collection<String>.

                    Originally posted by Jonathan Alvarsson View Post
                    If you have your entity in Persistant set it uses the hashcode to figure out which hashbucket to put the object in. If you change the object and the hashcode a contains() call probably return false since the new hashcode does not reference the old hashbucket. I also think that if equals have been changed the same thing happens since if more than one object is in a hashbucket equals is used to identify the sought after object. Hence fields that can change can not be used for equals and hashcode if you want to use the hashset as a hashset...
                    Sorry I meant a concrete example in the sense of some code you are working with at the moment.
                    Last edited by karldmoore; Aug 29th, 2007, 11:53 AM.

                    Comment


                    • #11
                      Originally posted by karldmoore View Post
                      Sorry I meant a concrete example in the sense of some code you are working with at the moment.
                      Hm well I don't really have any code for this since I am still planning this project. But say that you have a user with a name and a password and you wan't to be able to edit both. Then there is no good key so an id number would be needed. The easist way is to have the database generate this with using the native id settings in Hibernate. But say that you wan't to generate 10 Users put them in a set on some entity and store all by saving the entity. This would work as long as the hashcode does not depend on the id. Then you edit the username of one of those Users. Save the user and do a contains(editedUser) on the set. If the hashcode depends on the username this call will return false even though exactly the same object that is used in the contains(editedUser) call already is in the hashset. Since the hashCode() has changed. So this is clearly not the way to go...

                      Comment

                      Working...
                      X