2017-02-15 65 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,除非绝对必要,并优化您的存储库代码,以便在可能的情况下持续或合并实体之前从数据库中收集所有实体状态。