liveBook · Manning

hashCode method

As explained in Java Persistence with Spring Data and Hibernate epub

The hashCode method is the Java object method that returns an integer hash value used by hash-based collections.

A HashSet uses hashCode() alongside equals() to store and compare objects. When equality is redefined, both methods must agree: equal instances must return the same hash value. Otherwise, a set may fail to treat equivalent objects as one element. section 8.2.1 section 10.3.2

Listing 8.13 Implementing custom equality with equals() and hashCode()
Path: Ch08/mapping-collections/src/main/java/com/manning/javapersistence
 /ch08/setofembeddables/Image.java
 
@Embeddable
public class Image {
     // . . .
@Override
public boolean equals(Object o) {                                #1
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Image image = (Image) o;
    return width == image.width &&
           height == image.height &&
           filename.equals(image.filename) &&
           item.equals(image.item);
}
 
@Override
public int hashCode() {                                         #2
    return Objects.hash(filename, width, height, item);
}
    // . . .
}
#1 This custom equality check in <kbd>equals()</kbd> compares all values of one <kbd>Image</kbd> to the values of another <kbd>Image</kbd>. If all values are the same, the images must be the same.
#2 The <kbd>hashCode()</kbd> method has to fulfill the contract requiring that if two instances are equal, they must have the same hash code.

An @Embeddable Image compares its values in equals() and hashes the same values with Objects.hash(). This gives a set value-based equality rather than the default object-identity comparison. Override both methods for embeddable value types, especially when they are stored in sets or used as map keys. section 8.2.1

Entities need a different decision. Within one persistence context, repeated loads of a database row return the same Java instance. Loads in separate contexts can produce distinct instances representing that row. Custom equals() and hashCode() matter when detached entities must compare equal, particularly in sets or as map keys; merely displaying a detached entity does not require them. section 10.3.1

Choose an entity’s hash input with its lifecycle in mind:

  • Avoid a generated database identifier: a transient entity can enter a Set before Hibernate assigns its identifier. Saving it would then change its hash value while it is in the set. section 10.3.2
  • Use a business key for custom equality when detached instances must compare equal. Define hashCode() from the same key used by equals(). section 10.3.2
Listing 10.3 Custom implementation of User equality
@Entity
@Table(name = "USERS",
       uniqueConstraints =
        @UniqueConstraint(columnNames = "USERNAME"))
public class User {
    @Override
    public boolean equals(Object other) {
        if (this == other) return true;
        if (other == null) return false;
        if (!(other instanceof User)) return false;
        User that = (User) other;
        return this.getUsername().equals(that.getUsername());
    }
    @Override
    public int hashCode() {
        return getUsername().hashCode();
    }
    //  . . .
}

The User implementation compares usernames and returns the username’s hash code; the mapping also declares a database uniqueness constraint for that column. The accompanying detached-instance example shows references loaded in separate persistence contexts occupying one HashSet entry. section 10.3.2

How Java Persistence with Spring Data and Hibernate epub covers it

How deep it goes
Works through paired equals() implementations and the lifecycle failure caused by hashing a generated identifier.
Examples
Uses an embeddable Image hashed with Objects.hash() and a User hashed by its unique username.
What it assumes
Assumes basic Java collection use while explaining how persistence contexts affect entity identity.
What you can do after
Build it from scratch by pairing hashCode() with equals() and choosing hash inputs that remain suitable across persistence transitions.
How it connects
Connects hashCode() to equals(), HashSet, embeddable value types, detached entities, persistence contexts, and business keys.

Also explained in

Compare how 2 books explain hashCode method →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Java Persistence with Spring Data and Hibernate epub. The section links point to the parts of the book it draws on.