13 Replies Latest reply on Jan 5, 2013 2:07 PM by pedrokowalski

    Entity hashCode and equals overriding

    fabiovalse

      Hi there,

       

      I'm having some problems overring hashCode() and equals() methods of an entity Book. This is my code:

       

      ------------------------------------------------------------------------

      @Override

                public int hashCode() {

                          int hash = 1;

                    hash = hash * 31 + this.isbn.hashCode();

                    return hash;

                }

      @Override

                public boolean equals(Object o) {

                   if (o==this)

                       return true;

                   if (o instanceof Book) {

                       return (this.isbn == ((Book) o).getIsbn());

                   }

                   return false;

                }

      ------------------------------------------------------------------------

       

      The problem is that when I try to add a book to a hashMap like here:

       

      ------------------------------------------------------------------------

      @Override

          public void addArticle(Book book, Integer quantity) {

                    Integer currentQuantity = cart.getArticles().get(book);

         

                    System.out.println(currentQuantity);

          

              if (currentQuantity == null) {

                        currentQuantity = 0;

              }

              currentQuantity += quantity;

              cart.getArticles().put(book, currentQuantity);

          }

      ------------------------------------------------------------------------

       

      The currentQuantity Integer is always null even if in the hashMap there's already the Book that i'm adding.

       

      Maybe it's a problem of my hashCode and equals implementation but i've tried using a hashCode() that return always 1 and with an equals that return always true and currentQuantity is still null.

      Can someone give me a hint?

       

      Thank you in advance

        • 1. Re: Entity hashCode and equals overriding
          pedrokowalski

          Hi Fabio,

           

          Could you post what does your Cart entity looks like? How is the cart.getArticles() map defined?

           

          Cheers!

          Piotr

          • 2. Re: Entity hashCode and equals overriding
            fabiovalse

            This is my Cart Entity class:

             

            -----------------------------------------------------------------

            @Entity

            @Table(name = "carts")

            public class Cart implements Serializable {

            private static final long serialVersionUID = 3L;

             

                      public Cart() {

                    super();

                }

             

            @Id

                private String username;

            @ElementCollection

                @CollectionTable(name="cartsbooks", joinColumns=@JoinColumn(name="username"))

                @Column(name="quantity")

                @MapKeyJoinColumn(name="isbn", referencedColumnName="isbn")

                private Map<Book,Integer> articles;

            private float bill;

             

                      public String getUsername() {

              return username;

                      }

                      public void setUsername(String username) {

                                this.username = username;

                      }

                      public Map<Book,Integer> getArticles() {

              return articles;

                      }

                      public void setArticles(Map<Book,Integer> articles) {

                                this.articles = articles;

                      }

                      public float getBill() {

              return bill;

                      }

                      public void setBill(float bill) {

                                this.bill = bill;

                      }

            }

            -----------------------------------------------------------------

             

            As you can see the getArticles() method returns a HashMap<Book, Integer>, so the subsequent call get(book) should return an Integer value.

             

            Thank you!

            • 3. Re: Entity hashCode and equals overriding
              pedrokowalski

              Did you try creating some simple test - persist some data, commit the transaction. check the database state and then fetch the entity and make sure articles are retrieved correctly?

               

              How does the Book entity looks like? Does it have ISBN as primary key?

              • 4. Re: Entity hashCode and equals overriding
                fabiovalse

                Yes, now in my application I can persist books and retrieve them. The problem is when the addArticle() is executed.

                 

                In fact since

                 

                Integer currentQuantity = cart.getArticles().get(book);

                 

                return always null then the book is added on the database but as a different record.

                 

                Thank you!

                • 5. Re: Entity hashCode and equals overriding
                  pedrokowalski

                  Where is the 'cart' variable coming from in your addArticle() method?

                  Are you in the active transaction?

                  Is the cart.getArticles() empty or does contain some entries?

                  • 6. Re: Entity hashCode and equals overriding
                    fabiovalse

                    The cart variable is inside the CartBean:

                    -----------------------------------------------------------------------

                    @Stateful

                    @Remote(ICart.class)

                    public class CartBean implements ICart {

                              @PersistenceContext(unitName = "JPABOOK", type=PersistenceContextType.EXTENDED)

                        EntityManager entityManager;

                              private Cart cart = null;

                     

                        public CartBean() {}

                       

                        @Override

                        public void create(String username) {

                                  cart = entityManager.find(Cart.class, username);

                        

                            if (cart == null) {

                                      cart = new Cart();

                                      cart.setUsername(username);

                                      cart.setBill(0);

                                      entityManager.persist(cart);

                            }

                        }

                        @Override

                        public void addArticle(Book book, Integer quantity) {

                                  Integer currentQuantity = cart.getArticles().get(book);

                       

                                  System.out.println(currentQuantity);

                        

                            if (currentQuantity == null) {

                                      currentQuantity = 0;

                            }

                            currentQuantity += quantity;

                            cart.getArticles().put(book, currentQuantity);

                        }

                    -----------------------------------------------------------------------

                     

                    The cart it could be empty or containg some entries.

                    • 7. Re: Entity hashCode and equals overriding
                      pedrokowalski

                      If you invoke addArticle(-) for the first time - the cart.getArtiles() is empty.

                       

                      If you invoke addArticle(-) again - the cart.getArticles().get(book) will return null, but will the cart.getArticles() be empty? Try debugging it - is the previous article in the map (then you have a problem with hashCode and/or equals) or it's not there (and you have a problem with persistence).

                      1 of 1 people found this helpful
                      • 8. Re: Entity hashCode and equals overriding
                        fabiovalse

                        If I invoke one time addArticle() method then the cart is not empty but cart.getArticles().get(book) always return null even if the cart contains some entries. When I got this situation i figured out that the problem was the lack of hashCode and equals. Now that the methods are implemented nothing is changed. Moreover i've tried using a hashCode() that return always 1 and equals() that return always true but currentQuantity is still null.

                         


                        • 9. Re: Entity hashCode and equals overriding
                          pedrokowalski

                          Ok, so you have some entries and you can't fetch them. You're saying that your persistence is working correctly, so can you investigate a little more about what entrries are in cart.getArticles()? Fetch them, fetch their hashCodes. It seems rather impossible that you have hashcode and equals methods that returns always the same value (1 and true), you have a collection with entities and still you're retrieving null...

                          1 of 1 people found this helpful
                          • 10. Re: Entity hashCode and equals overriding
                            fabiovalse

                            I tried to use equals() returning true and hashCode returning 1 only for testing. Because in this way if all books has the same hashcode it would like "all the books are the same". But since even in this case the call returns null i've tried with normal equals() and hashCode() to print the hashCode of the book inserted in the cart and the hashCode of the book inserted. They were equals.

                            However i can retry to investigate deeply.

                             

                            Thank u Piotr!

                            • 11. Re: Entity hashCode and equals overriding
                              pedrokowalski

                              This is really weird Fabio.

                               

                              So you have a Map<Book, Integer> with one element - entry1 which key hashCode yields to 1 and equals always returns true.

                               

                              Then you have a Book instance - b1 which hashCode yields to 1 and equals always returns true.

                               

                              In this way you ask the Map<Book, Integer> for an entry with key b1. The hashCode == 1, so the bucket in the map is located correctly; the equals always returns true, so the element must be properly returned...

                               

                              Can it be some caching problem between you changing the code, deploying it on the server and running again?

                               

                              Saying it all - it seems like a problem not related with the JPA / persistence / database.

                              • 12. Re: Entity hashCode and equals overriding
                                fabiovalse

                                I've just fix the problem! I've changed the code in this way:

                                 

                                -------------------------------------------------------

                                @Override

                                          public boolean equals(Object o) {

                                             if (o==this)

                                                 return true;

                                             if (o instanceof Book) {

                                                       if (this.isbn.compareTo(((Book) o).getIsbn()) == 0)

                                                                 return true;

                                                       else return false;

                                             }

                                             return false;

                                          }

                                -------------------------------------------------------

                                 

                                The problem was the comparison between string! Now I use the compareTo() method and everything correctly works.

                                 

                                Thank you for your time Piotr!

                                • 13. Re: Entity hashCode and equals overriding
                                  pedrokowalski

                                  It's geat it works, but it also should work if you returned the same value from hashcode and equals... the strngs comparison was not the issue it that situation, right?