2017-02-15 13 views
0

Я получаю исключение ниже. Я использую spring-data, JPA & & Hibernate У меня есть метод, который выполняет некоторые обновления для некоторых объектов и запросов. Прежде, чем транзакция завершится и до вызова myRespositoryEntity.save (myEntity), я думаю, из-за сохранения согласованности транзакции hibernate/jpa выполняет флеш, и на этом флеше похоже, что он пытается сделать упор, а не слияние. Я знаю, что у меня есть отдельные элементы, но что это исключение возникает при промывке и не в сохранении? Если я попытаюсь сохранить объект в начале транзакции, исключение не произойдет.Отдельный объект на флеше

У меня есть отдельные объекты, потому что я конвертирую из объектов DTO в объекты Entities, а некоторые существующие объекты не помещаются в диспетчер сущности. Но если бы я не получил это случайное поведение при флеше, слияние сделало бы все правильно

Любое обходное решение? Есть идеи?

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, если это абсолютно необходимо, и оптимизировать код вашего репозитория, чтобы вы могли собрать все сущность из базы данных до того, как сможете или скомпилировать объекты, если сможете.