提问者:小点点

齐平分离实体


我得到以下异常。我正在使用一个spring-data,JPA

我分离了实体,因为我从DTO转换为实体对象,并且一些现有对象没有放在实体管理器中。但是如果我没有得到这种随机刷新行为,合并会做正确的事情

有什么变通办法吗?有什么想法吗?

Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: package.MyEntity
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
    at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:838)
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:831)
    at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:357)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:379)
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118)
    at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:167)
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:158)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:91)
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:61)
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1227)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1293)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)
    at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573)
    at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:495)
    at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:71)
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:206)
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:78)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:102)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:92)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:482)
    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)
    ... 130 common frames omitted

共1个答案

匿名用户

Hibernate使用FlushMode.AUTO作为默认值,这就是您观察此行为的原因。

基本上,当设置了FlushMode.AUTO时,Hibernate会在执行任何查询操作之前检查会话中的任何实体状态是否为脏状态。如果检测到脏状态,它可能会选择刷新状态,以便这些更改将反映在查询结果中。

附带说明一下,Hibernate确实进行了一些优化,以避免在您正在执行的查询没有任何会影响结果的脏实体状态时总是刷新

您可以通过将刷新模式类型更改为COMMIT来禁用此行为。这基本上会导致Hibernate在事务提交之前不会刷新任何数据库更改。这可能会根据您的使用情况产生一些不希望的副作用,因此请预先警告。

如果可能的话,我建议不要使用FlushMode,除非绝对必要,并优化您的存储库代码,以便在持久化或合并实体之前从数据库中收集所有实体状态。