title: Spring, JPA and Rest and Duplicate entry for key 'PRIMARY'
body: <p>I'm just starting to learn Spring and JPA and I've run into a bit of a wall trying to figure out what is causing my app to try and insert cascaded values in multiple times. I have the following structure:</p>
  
  <p>pom.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
      &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  
      &lt;groupId&gt;com.test&lt;/groupId&gt;
      &lt;artifactId&gt;core&lt;/artifactId&gt;
      &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
      &lt;packaging&gt;jar&lt;/packaging&gt;
  
      &lt;name&gt;core&lt;/name&gt;
      &lt;description&gt;Demo project for Spring Boot&lt;/description&gt;
  
      &lt;parent&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
          &lt;version&gt;2.0.3.RELEASE&lt;/version&gt;
          &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
      &lt;/parent&gt;
  
      &lt;properties&gt;
          &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
          &lt;project.reporting.outputEncoding&gt;UTF-8&lt;/project.reporting.outputEncoding&gt;
          &lt;java.version&gt;1.8&lt;/java.version&gt;
      &lt;/properties&gt;
  
      &lt;dependencies&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-data-rest&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;mysql&lt;/groupId&gt;
              &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
              &lt;artifactId&gt;lombok&lt;/artifactId&gt;
              &lt;optional&gt;true&lt;/optional&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
              &lt;scope&gt;test&lt;/scope&gt;
          &lt;/dependency&gt;
      &lt;/dependencies&gt;
  
      &lt;build&gt;
          &lt;plugins&gt;
              &lt;plugin&gt;
                  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
              &lt;/plugin&gt;
          &lt;/plugins&gt;
      &lt;/build&gt;
  &lt;/project&gt;
  </code></pre>
  
  <p>Person.java</p>
  
  <pre><code>@Data
  @Entity
  @EqualsAndHashCode(callSuper = false)
  @Table(name = "persons")
  public class Person extends Auditable&lt;String&gt; {
  
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      @Column(name = "user_id", unique = true, nullable = false)
      private Long id;
  
      private String firstName;
      private String lastName;
  
      @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST} )
      @JoinColumn(name = "hometown_id")
      private City hometown;
  
      protected Person() {
      }
  
      public Person(String firstName, String lastName, City hometown) {
          this.firstName = firstName;
          this.lastName = lastName;
          this.hometown = hometown;
      }
  }
  </code></pre>
  
  <p>City.java</p>
  
  <pre><code>@Data
  @Entity
  @EqualsAndHashCode(callSuper=false)
  @Table(name = "cities")
  public class City extends Auditable&lt;String&gt; {
  
      @Id
      @Size(max = 255)
      @Column(name = "city_name", unique = true)
      private String cityName;
  
      @OneToMany(mappedBy = "hometown", cascade = CascadeType.ALL)
      @EqualsAndHashCode.Exclude
      private Set&lt;Person&gt; inhabitants = new HashSet&lt;&gt;(); 
  
      protected City() {}
  
      public City(String cityName) {
          this.cityName = cityName;
      }
  }
  </code></pre>
  
  <p>My repositories:</p>
  
  <pre><code>@RepositoryRestResource(exported = false)
  public interface CityRepository extends PagingAndSortingRepository&lt;City, Long&gt; {}
  
  @RepositoryRestResource(collectionResourceRel = "people", path = "people")
  public interface PersonRepository extends PagingAndSortingRepository&lt;Person, Long&gt; {}
  </code></pre>
  
  <p>So, the first time I do the following:</p>
  
  <pre><code>REQUEST:
  
  curl -X POST \
    http://localhost:8080/api/persons \
    -H 'cache-control: no-cache' \
    -H 'content-type: application/json' \
    -d '{
      "firstName": John",
      "lastName": "Doe",
      "hometown": {
          "cityName": "Los Angeles"
      }
  }'
  
  RESPONSE:
  
  {
      "firstName": John",
      "lastName": "Doe",
      "qualifications": "asdasdasdasd",
      "hometown": {},
      "_links": {
          "self": {
              "href": "http://localhost:8080/api/persons/1"
          },
          "person": {
              "href": "http://localhost:8080/api/persons/1"
          }
      }
  }
  </code></pre>
  
  <p>If I refresh the list from /api/persons, I see that the correct relationship exists. </p>
  
  <pre><code>{
      "firstName": John",
      "lastName": "Doe",
      "qualifications": "asdasdasdasd",
      "hometown": {
          "_links": {
              "requisitions": {
                  "href": "http://localhost:8080/api/requisitions/3"
              }
          }
      },
      "_links": {
          "self": {
              "href": "http://localhost:8080/api/persons/1"
          },
          "person": {
              "href": "http://localhost:8080/api/persons/1"
          }
      }
  }
  </code></pre>
  
  <p>But the second person I try and persist with the same hometown, an error is thrown:</p>
  
  <pre><code>REQUEST:
  
  curl -X POST \
    http://localhost:8080/api/persons \
    -H 'cache-control: no-cache' \
    -H 'content-type: application/json' \
    -d '{
      "firstName": Jane",
      "lastName": "Doe",
      "hometown": {
          "cityName": "Los Angeles"
      }
  }'
  
  RESPONSE:
  
  {
      "cause": {
          "cause": {
              "cause": null,
              "message": "Duplicate entry 'Los Angeles' for key 'PRIMARY'"
          },
          "message": "could not execute statement"
      },
      "message": "could not execute statement; SQL [n/a]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"
  }
  </code></pre>
  
  <p>How do I configure the relationships to persist a new version ONLY if it doesn't already exist? I know I can do it by making multiple API calls to lookup/persist the city first, but thats way too many network hops to just save a small piece of data.</p>
  
  <p>Side question, I have the fetchType set to EAGER on the hometown column, but I still only just get a link. Is there a way to make it pre-resolve the data before sending it?</p>
  
  <p>Thanks!</p>