保存和对象时抛出 JPA EntityExistsException

问题描述 投票:0回答:1

我的项目中有以下 2 个对象,它们共享公共复合主键和 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.
}

我在下面的代码中使用这些,其中所有内容都应该在一个事务中运行:

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>
this.transactionManager.commit(status); // Commit is never actually reached. Exception is thrown before

我收到以下错误:

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.executeCobaExport(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

我真的不知道该怎么办。似乎不喜欢 JPARepository 已保存的 Model 实例再次在 Graph 对象中使用。但同时,Graph 对象没有 Persist Cascade,因此它不应该尝试持久化 Model 对象。

有人可以帮助我吗?

hibernate jpa spring-data-jpa
1个回答
0
投票

考虑到

OneToOne
关系,首先保存模型实体很重要,以避免在保存图形实体时出现任何问题。 所以你需要像这样更新代码:

this.modelRepository.saveAndFlush(model);

使用

saveAndFlush
,您可以确保模型实体立即保存到数据库并减少冲突的机会。

© www.soinside.com 2019 - 2024. All rights reserved.