javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session

I have the following 2 objects in my project that share the common Composite Primary Key as and ID:

@Entity
@Immutable
@Cacheable(true)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Table(name = "Models")
public class Model implements Serializable {

    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private Key id;

    @Column(name = "ver_id")
    private String versionId;

// etc.
}
@Entity
@Table(name = "Graphs")
public class Graph implements Serializable {

    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private Key id;
    
    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumns({@JoinColumn(name = "PCG_ID", referencedColumnName = "MOD_ID"),
        @JoinColumn(name = "PCG_LANGUAGE", referencedColumnName = "MOD_LANGUAGE") })
    @MapsId
    private Model model;
// etc.
}
@Embeddable
public class Key implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name = "MOD_ID")
    private String modelId;

    @Column(name = "MOD_LANGUAGE")
    private String language;
// etc.
}

I’m using these in the following piece of code where everything should be run inside one transaction:

TransactionStatus status = null;
status = this.transactionManager.getTransaction(null);
Model model = new Model();
model.setId(new ModelKey("123", "EN");
// rest of Model setters
this.modelRepository.save(model); // public interface ModelRepository extends JpaRepository<Model, Key>
Graph sgraph = new Graph();
graph.setModel(model);
// rest of Graph setters
this.graphRepository.save(graph); // public interface GraphRepository extends JpaRepository<Graph, Key>

and I’m getting the following error:

org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session : [com.company.app.model.app.Model#Key [id=123, language=EN]]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.company.app.model.app.Model#Key [id=123, language=EN]]
	at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:400)
	at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:235)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)
	at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
	at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241)
	at com.sun.proxy.$Proxy90.save(Unknown Source)
	at com.company.app.dataaccess.service.GraphService.insert(GraphService.java:29)
	at com.company.app.appNPExporter.createGraphData(appNPExporter.java:776)
	at com.company.app.appNPExporter.handleModel(appNPExporter.java:633)
	at com.company.app.appNPExporter.handleChangedModel(appNPExporter.java:559)
	at com.company.app.appNPExporter.handleChangedModels(appNPExporter.java:507)
	at com.company.app.appNPExporter.execute(appNPExporter.java:340)
	at com.company.app.appExporterLauncher.executeExport(appExporterLauncher.java:148)
	at com.company.app.appExporterLauncher.main(appExporterLauncher.java:67)
Caused by: javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.company.app.model.app.Model#Key [id=123, language=EN]]
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:123)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
	at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:786)
	at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748)
	at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:298)
	at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:510)
	at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:434)
	at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220)
	at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:153)
	at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:426)
	at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:263)
	at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192)
	at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:134)
	at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185)
	at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128)
	at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:55)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
	at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:756)
	at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:742)
	at jdk.internal.reflect.GeneratedMethodAccessor86.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:315)
	at com.sun.proxy.$Proxy84.persist(Unknown Source)
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:666)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:530)
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:286)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:640)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:139)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:76)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
	... 15 common frames omitted

I really don’t know what to do with this. It seems like it doesn’t like that the instance of Model that is already saved by the JPARepository is again being used in the Graph object. But at the same time, the Graph object doesn’t have Persist Cascade so it should not try to persist the Model object.

I’m using Hibernate 5.6.15.Final

Can anyone help me please?

modelRepository.save(model) probably calls EntityManager#merge, which returns a new object instance that is managed. You have to use that returned object instance when calling graph.setModel(model), otherwise you will see that exception.
There can only be one object in the persistence context for an entity type with the same id, which is what the exception is telling you.

1 Like