我在使用Spring Data时遇到了与hibernates级联操作有关的一些问题。 起初我的实体类:
@Entity
public class EntityOne {
@Id
private String code;
@ManyToOne(optional = false, cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.PERSIST })
private EntityTwo entityTwo;
}
@Entity
public class EntityTwo {
@Id
private String code;
@OneToMany(mappedBy = "entityTwo")
private Set<EntityOne> entitiesOne;
}
我已经编写了一个基于Spring Batch的EntityImport,它使用了一个Processer,它通过Repository.findOne(example)
检查是否已有现有实体(并进行一些深度属性合并)和RepositoryItemWriter
来写“创建”实体进入数据库。
现在我的问题:如果数据库中没有现有的ParentData,一切正常。导入会创建一个EntityOne
,其链接为EntityTwo
。使用保存后,两个实体都保留在数据库中。
但是当我尝试重复这个过程时,我得到一个DataIntegrityViolationException
Caused by: javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [EntityTwo#EntityTwoCode]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1735)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:524)
at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:71)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne(SimpleJpaRepository.java:425)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
奇怪的是,我在Repository.save(EntityOne)
调用时没有得到这个,但在Repository.findOne(example.of(EntityOne))
调用之前,这导致了hibernate的自动刷新导致上面的异常。