title: SpringBoot, @EmbeddedId equals()/hashCode()
body: <p>I have this class, which I use it elsewehere as an <code>@EmbeddedId</code>:</p>
  
  <pre><code>@Embeddable
  public class Pk implements Serializable {
      @NotNull
      @Column( nullable = false)
      private UUID id = UUIDGenerator.EMPTY_UUID;
  
      @NotNull
      @Column( nullable = false)
      private String name = "";
  
      public UUID getId() {
          return id;
      }
  
      public void setId(UUID id) {
          this.id = id;
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      @Override
      public int hashCode() {
          return this.id.hashCode();
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj) {
              return true;
          }
  
          if (obj == null || !(obj instanceof PK)) {
              return false;
          }
  
          Pk other = (Pk)obj;
  
          return this.id.equals(other.getId());
      }
  }
  </code></pre>
  
  <p>However, SpringBoot Repository does not seem to be using the equals()/hashCode() functions when deciding when it should create a new entity or update an existing one. Result is that two entities that should be considered equal, they are not and the repository creates new entries instead of updating existing ones.</p>
  
  <p>A breakpoint in equals() is never reached, which makes me wonder if the repository is using this at all (Using SpringBoot 1.5.5).</p>
  
  <p>Note that only one of the two properties is used in the equality test. The other one is a natural key (always unique, but not immutable). </p>
  
  <p>Any ideas on why this is happening and how it can be fixed?</p>
  
  <p>Thanks in advance,</p>
  
  <p>PS: This is the class using it</p>
  
  <pre><code>@Entity
  public class Demo {
      @EmbeddedId
      Pk pk = new Pk();
  
      @NotNull
      @Column(nullable = false)
      private String dummy = "";
  
      //getters and setters
  }
  </code></pre>
  
  <p>And this is how it is used:</p>
  
  <pre><code>@Autowired
  DemoRepository demoRepository;
  
  public void updateDemo(Demo updatedDemo) {
      Optional&lt;Demo&gt; oldDemo =  
           demoRepository.findByPkId(updatedDemo.getPk().getId());
  
      //Do some sanity checks with the oldDemo
      //Creates new entry, even though it should have updated the old
      demoRepository.save(updatedDemo);       
   } 
  </code></pre>
  
  <p>======</p>
  
  <p>I am editing the question again, because after some debugging I realise that Hibernate does not indeed call the <code>hashCode()</code> function defined in the <code>@EmbeddedId</code> and instead uses its own <code>hashCode()</code> by practically summing the <code>hashCode()</code> of the <code>@EmbeddedId</code> properties.</p>
  
  <p>The actual code seems to be in <code>org.hibernate.type.ComponentType.java</code> where <code>Object x</code> is in my case of type <code>PK</code>. </p>
  
  <pre><code>public int getHashCode(Object x, SessionFactoryImplementor factory) {
      int result = 17;
  
      for(int i = 0; i &lt; this.propertySpan; ++i) {
          Object y = this.getPropertyValue(x, i);
          result *= 37;
          if (y != null) {
              result += this.propertyTypes[i].getHashCode(y, factory);
          }
      }
  
      return result;
  }
  </code></pre>
  
  <p>Is this the expected behavior? I was led to believe that one of the reasons you define your own <code>equals()/hashCode()</code> was so that JPA will decide whether to create a new entity or merge it to an existing one. If they are not used for this, what good are they?</p>