Spring управление транзакциями ломает каскад гибернации - PullRequest
1 голос
/ 05 мая 2010

У меня возникла проблема, когда добавление Spring управления транзакциями в приложение заставляет Hibernate выдавать следующую ошибку:

org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: org.fstrf.masterpk.domain.ReportCriteriaBean.treatmentArms
org.hibernate.engine.Collections.processDereferencedCollection(Collections.java:96)
org.hibernate.engine.Collections.processUnreachableCollection(Collections.java:39)
org.hibernate.event.def.AbstractFlushingEventListener.flushCollections(AbstractFlushingEventListener.java:218)
org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:77)
org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:135)
org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:72)
org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:905)
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:715)
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
$Proxy92.saveNewReportCriteria(Unknown Source)
org.fstrf.masterpk.domain.logic.MasterPkFacade.saveNewReportCriteria(MasterPkFacade.java:134)
org.fstrf.masterpk.controllers.ReportCriteriaController.setupReportType(ReportCriteriaController.java:302)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:585)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:413)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:134)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:310)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:297)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)

Я использую Spring 2.5 и аннотации для реализации этого управления. Вот класс, содержащий метод saveNewReportCriteria (который, как видно из трассировки стека, вызывает ошибку)

@Transactional(
     propagation = Propagation.REQUIRED,
     isolation = Isolation.DEFAULT,
     readOnly = false)
public class HibernateReportCriteriaDao implements ReportCriteriaDao{

private HibernateTemplate hibernateTemplate;

public Integer saveNewReportCriteria(ReportCriteriaBean reportCriteria) {
    hibernateTemplate.save(reportCriteria);

    List<Integer> maxIdList = hibernateTemplate.find("SELECT max(id) from ReportCriteriaBean");
        logger.info("ID of newly saved list is: " + maxIdList.get(0));
        return maxIdList.get(0);
    }

    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }
}

Затем я добавил следующие разделы в мои файлы конфигурации, чтобы сообщить Spring, что использую управление транзакциями на основе аннотаций:

<bean id="actgDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc/actg" />
    <property name="resourceRef" value="true" />
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="actgDataSource" />
</bean>

<tx:annotation-driven/>

Я почти уверен, что ошибка разыменования вызвана из-за прокси-класса, который Spring AOP создает и использует для управления транзакциями, но я понятия не имею, как мне его исправить.

Ответы [ 3 ]

1 голос
/ 02 декабря 2011

У меня возникла та же проблема (all-delete-orphan) при одновременном сохранении родительской и дочерней таблиц. Решение:

  1. Сначала сохранить только родителя
  2. получить дочерний элемент от родителя и удалить все старые дочерние данные в дочерней таблице
  3. добавить родительскую информацию к новым дочерним данным
  4. добавить новые дочерние данные
1 голос
/ 05 мая 2010

ошибка вполне может быть НЕ в этой функции, если вы внимательно посмотрите на трассировку стека, вы увидите, что ошибка вызывается из saveNewReportCriteria PROXY, а не из вашего класса. скорее всего, это было что-то ранее, что делало обновление или удаление и не было немедленно сброшено в БД hibernate, потому что таким образом можно оптимизировать определенные вещи.

Один из способов выяснить, что происходит, состоит в том, чтобы ставить .flush () в конце каждого запроса на удаление / обновление, что не всегда желательно, или, в качестве альтернативы, просто выполнить поиск того, где вы можете установить значение свойства memoryArms, чтобы установить значение null или новый List () - очистить список при спящем использовании list.clear (); который будет поддерживать коллекцию с Hibernate-прокси правильного типа.

0 голосов
/ 05 мая 2010

Видимо, моя проблема действительно заключалась в методе saveNewReportCriteria. При удалении второго запроса (вызов find () для максимального идентификатора) ошибка исчезла. Я понятия не имею, почему это так. Как я упоминал ранее, этот метод был хорош до добавления аннотаций управления транзакциями. Если кто-нибудь знает, что здесь происходит, я бы хотел узнать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...