0

I am facing problems implementing hashcode/equals in a simple Employee Entity below. My custom field upon which i want to implement equality is the "_id" field.

When i save two employee objects with the same value i.e. "111", I expect to save only one value in the database. However, i end up saving 2 employee records.

The entity code is as below

    @Entity
    @Table(name = "employee")
    public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "employee_id")
    private Long employeeId;

    @Column(name = "employeehexa_id") 
    private String _id;

    @Override
    public int hashCode() {
        HashCodeBuilder hcb = new HashCodeBuilder();
        hcb.append(_id);
        return hcb.toHashCode();
    }   


    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Employee)) {
            return false;
        }
        Employee that = (Employee) obj;
        EqualsBuilder eb = new EqualsBuilder();
        eb.append(_id, that._id);
        return eb.isEquals();
    }

    // Required Constructors, getters, setters not shown for brevity
   }

And the below is my call to save two object with same _id

@Autowired
private EmployeeRepo employeeRepo;

@RequestMapping("/test")
String Test() throws Exception {

    Employee e1 = new Employee("111");
    Employee e2 = new Employee("111");
     System.out.println(e1.equals(e2)); // prints true, implying hashcode and equals working fine
    employeeRepo.save(e1);
    employeeRepo.save(e2);//Both e1 and e2 are saved inspite of being equal

    return "Completed !";
}

The equality check seems to work fine. Is there something about save() of spring JpaRepository that causes this or is my understanding of how equality/hashcode contract is enforced incorrect ?

I thought i understood equality/hashcode but looks like that is not the case. Any help appreciated. Thx.

HopeKing
  • 3,317
  • 7
  • 39
  • 62
  • 1
    This has nothing to do with Spring Data JPA but merely with how JPA works. If you don't want to save it create a unique constraint on the database level. – M. Deinum Feb 05 '18 at 10:09

1 Answers1

2

According to this answer, https://stackoverflow.com/a/11881628/5695673, you probably have 2 records because your fields employeeId are differents for your entities, so for spring-data the two entities are differents.
To test if your equals()/hashCode() works as expected, you can try to put your entities in a collection which check object equality (i.e. a Set) and try to save all the set in one time.

Example:

Set<Employee> employees = new HashSet<Employee>();
employees.add( new Employee("111"));
employees.add( new Employee("111"));

System.out.println(employees.size()); //1
employeeRepo.save(employees); // 1 record

More information here: https://developer.jboss.org/wiki/EqualsandHashCode?_sscc=t

STaefi
  • 4,297
  • 1
  • 25
  • 43
gWombat
  • 517
  • 2
  • 11
  • thanks. Yes, I am aware of the collection approach. But was interested in saving separately. Is the only way to ensure that spring data save() enforces the hashcode/equals is to put objects in a collection and save them ? – HopeKing Feb 05 '18 at 10:10
  • IMO yes, but this is not a spring-data problem, this is more a JPA related topic. – gWombat Feb 05 '18 at 11:09