2017-02-15 40 views
0

我越來越波瀾異常。我正在使用彈簧數據,JPA & &休眠 我有一個方法,對一些實體和查詢做一些更新。 在事務完成之前並且在調用myRespositoryEntity.save(myEntity)之前,我猜想因爲保持事務的一致性,hibernate/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會在執行任何查詢操作之前檢查會話中的任何實體狀態是否是髒的。如果檢測到髒狀態,則可以選擇刷新狀態,以便這些更改將反映在查詢結果中。

作爲一個側面說明,休眠也有一些優化,以避免總是沖洗應該你不執行查詢有這將影響結果

任何骯髒的實體狀態您可以通過更改刷新模式禁用此行爲鍵入到COMMIT。這基本上會導致Hibernate在事務提交之前不會刷新任何數據庫更改。根據您的使用情況,這可能會產生一些不希望的副作用,因此應預先警告。

如果可能的話,我會建議單獨離開FlushMode,除非絕對必要,並優化您的存儲庫代碼,以便在可能的情況下持續或合併實體之前從數據庫中收集所有實體狀態。