title: How to avoid javax.persistence.EntityExistsException: different object with the same identifier?
body: <p>I have small study project, something like quiz API. When I try to save complex object (Exam), hibernate throws EntityExistsException. I get REST request with dto (CreateExamRequestDto), then I map this dto to an Entity and save it using Spring Data JPA.</p>
  
  <p>Here is my Entity classes:</p>
  
  <p>EXAM ENTITY:</p>
  
  <pre><code>@Entity
  @Table(name = "exams", uniqueConstraints = {@UniqueConstraint(columnNames = {
          "name",
          "category_id"
  })})
  public class Exam extends AbstractEntity {
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "exams_seq_gen")
      @SequenceGenerator(name = "exams_seq_gen", sequenceName = "exams_id_seq")
      @Column(name = "id")
      private Integer id;
      @Column(name = "name", nullable = false)
      private String name;
      @ManyToOne
      @JoinColumn(name = "category_id", nullable = false)
      private Category category;
      @ManyToOne
      @JoinColumn(name = "owner_id", nullable = false)
      private User owner;
      @OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
      private List&lt;Section&gt; sections;
      @Column(name = "target_score", nullable = false)
      private Integer targetScore;
      @OneToMany()
      private List&lt;ExamResult&gt; results;
  
      @Transient
      private ExamResult result;
  
      //public constructor, getters, setters, hashcode and equals
  }
  </code></pre>
  
  <p>SECTION ENTITY:</p>
  
  <pre><code>@Entity
  @Table(name = "exam_sections", uniqueConstraints = @UniqueConstraint(columnNames = {
          "name",
          "exam_id"
  }))
  public class Section extends AbstractEntity {
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "exam_sections_seq_gen")
      @SequenceGenerator(name = "exam_sections_seq_gen", sequenceName = "exam_sections_id_seq")
      @Column(name = "id")
      private Integer id;
      @Column(name = "name", nullable = false)
      private String name;
      @Column(name = "question_weight", nullable = false)
      private Integer questionWeight;
      @Column(name = "target_questions", nullable = false)
      private Integer targetQuestions;
      @OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
      private List&lt;Question&gt; questions;
      @ManyToOne
      @JoinColumn(name = "exam_id", nullable = false)
      private Exam exam;
  
      //public constructor, getters, setters, hashcode and equals
  }
  </code></pre>
  
  <p>QUESTION ENTITY:</p>
  
  <pre><code>@Entity
  @Table(name = "questions")
  public class Question extends AbstractEntity {
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "questions_seq_gen")
      @SequenceGenerator(name = "questions_seq_gen", sequenceName = "questions_id_seq")
      @Column(name = "id")
      private Integer id;
      @Column(name = "text", nullable = false)
      private String text;
      @Column(name = "type", nullable = false)
      @Enumerated(EnumType.STRING)
      private QuestionType type;
      @OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
      private List&lt;Answer&gt; answers;
      @ManyToOne
      @JoinColumn(name = "section_id")
      private Section section;
  
      //public constructor, getters, setters, hashcode and equals
  }
  </code></pre>
  
  <p>ANSWER ENTITY:</p>
  
  <pre><code>@Entity
  @Table(name = "answers")
  public class Answer extends AbstractEntity {
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "answers_seq_gen")
      @SequenceGenerator(name = "answers_seq_gen", sequenceName = "answers_id_seq")
      @Column(name = "id")
      private Integer id;
      @Column(name = "text", nullable = false)
      private String text;
      @Column(name = "correct", nullable = false)
      private Boolean correct;
      @ManyToOne
      @JoinColumn(name = "question_id", nullable = false)
      private Question question;
  
      //public constructor, getters, setters, hashcode and equals
  }
  </code></pre>
  
  <p>And code that save it all: </p>
  
  <pre><code>@Override
  @Transactional
  public ExamShortDto createExam(CreateExamRequestDto request) {
      Exam exam = examMapper.mapToEntity(request, user);
      exam = examRepository.save(exam);             &lt;&lt;----- HERE
  
      return examMapper.mapToShortDto(exam);
  }
  </code></pre>
  
  <p>On pointed line I've got next exception:</p>
  
  <p>2017-09-05 17:24:12.278 ERROR 14024 --- [nio-8080-exec-1] o.s.b.w.servlet.support.ErrorPageFilter  : Forwarding to error page from request [/api/exam] due to exception [A different object with the same identifier value was already associated with the session : [org.yvasylchuk.testit.domain.entity.exam.Answer#191]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [org.yvasylchuk.testit.domain.entity.exam.Answer#191]]</p>
  
  <pre><code>org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session : [org.yvasylchuk.testit.domain.entity.exam.Answer#191]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [org.yvasylchuk.testit.domain.entity.exam.Answer#191]
      at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:395) ~[spring-orm-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:226) ~[spring-orm-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:499) ~[spring-orm-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) ~[spring-tx-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:216) ~[spring-tx-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153) ~[spring-tx-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:134) ~[spring-data-jpa-2.0.0.RC2.jar:na]
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.0.0.RC2.jar:na]
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.0.RC3.jar:5.0.0.RC3]
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.0.RC3.jar:5.0.0.RC3]
      at com.sun.proxy.$Proxy130.save(Unknown Source) ~[na:na]
      at org.yvasylchuk.testit.service.exam.impl.ExamFacadeImpl.createExam(ExamFacadeImpl.java:143) ~[classes/:0.0.1-SNAPSHOT]
  
      ......
  
  Caused by: javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [org.yvasylchuk.testit.domain.entity.exam.Answer#191]
      at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:116) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:771) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:458) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:383) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:491) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:423) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:386) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:281) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:804) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:771) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:458) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:383) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:491) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:423) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:386) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:281) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:804) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:771) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:458) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:383) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:491) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:423) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:386) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:281) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:780) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:765) ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]
      ...
  </code></pre>
  
  <p>SOLUTION:</p>
  
  <p>I just change one line in Answers Entity from:</p>
  
  <pre><code>@Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "answers_seq_gen")
  HERE --&gt;&gt; @SequenceGenerator(name = "answers_seq_gen", sequenceName = "answers_id_seq")
  @Column(name = "id")
  private Integer id;
  </code></pre>
  
  <p>to:</p>
  
  <pre><code>@Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "answers_seq_gen")
  HERE --&gt;&gt; @SequenceGenerator(name = "answers_seq_gen", sequenceName = "answers_id_seq", allocationSize = 200)
  @Column(name = "id")
  private Integer id;
  </code></pre>