2010-10-07 13 views
5

Piszę prostą aplikację (Spring + Hibernate + PostgreSql db). Po prostu próbuję zbudować przykładowy obiekt i utrzymywać go w db.Wiosenna transakcja - automatyczne wycofywanie wcześniejszych aktualizacji db, gdy jedna aktualizacja bazy danych nie powiedzie się

uruchomić prostą klasę Java główne metody gdzie mam załadowany ApplicationContext i mam odniesienie do klasy usług, jak poniżej kontekście

TestService srv = (TestService)factory.getBean("testService"); 

Application - Kontekst:

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactoryVsm" /> 
</bean> 

<bean id="testService" class="com.test.service.TestServiceImpl"> 
    <property name="testDao" ref="testDao"/> 
</bean> 

<bean id="testDao" class="com.test.dao.TestDaoImpl> 
    <property name="sessionFactory" ref="sessionFactoryVsm"/> 
</bean> 

W TestService wstrzyknąłem TestDao. W metodzie usługi testowej skonstruowałem dla pracowników obiekty emp1 i emp2 i dzwoniąc do dao dwa razy, aby zaktualizować.

kod TestDaoImpl:

public void saveOrUpdate(BaseDomainModel baseObject) { 

    Session session = null; 
    try { 
     session = getHibernateTemplate().getSessionFactory().openSession(); 
     session.saveOrUpdate(baseObject); 
     session.flush(); 
    } catch (Exception e) { 
     logger.error("Generic DAO:saveOrUpdate::" + e); 
     e.printStackTrace(); 
    } finally { 
     if (session != null) { 
      session.close(); 
     } 
    } 

} 

Kiedy zmiana emp2 nie powinno emp1 też nie. Jak mogę to zrobić. Proszę o poradę

góry dziękuję

Aktualizacja:

Thanks Nanda. Próbowałem transakcji deklaratywnej. Ale to nie działa. emp1 zostaje utrwalone i nie jest wycofywane, drugie wywołanie dao kończy się niepowodzeniem. Dodałem porady dotyczące transakcji do metody.

aby sprawdzić, czy rada transakcja jest stosowana lub nie zmieniłem rozchodzenie się "NOT_SUPPORTED". ale nadal emp1 zostaje uparty. oczekiwanie jest, że powinniśmy mieć wyjątek typu Transaction Not Supported. proszę o poradę.

AKTUALIZACJA

@seanizer - dzięki za aktualizację. Próbowałem nawet dodać
@ Transakcja (propagacja = Propagacja.NOT_SUPPORTED) publicznych void saveEmp (Employee emp) do tej metody usługi. Ale to nie zadziałało. Ponadto iterowanie kolekcji jest dobre tylko wtedy, gdy muszę zadzwonić do jednego dao. Jeśli na wypadek, gdybym musiał zadzwonić do dwóch różnych dao, aby kontynuować obj1 i obj2 - to może nie pomóc. Aby sprawdzić, czy transakcja jest stosowana, otrzymuję @Transactional (propagacja = Propagacja.NOT_SUPPORTED). Ale nadal obj1 się utrzymywał. Wątpię, czy podana konfiguracja/adnotacja xml jest poprawna. sprawdź

<bean id="txManager" 
     class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactoryVsm" /> 
    </bean> 

<tx:advice id="txAdvice" transaction-manager="txManager"> 
    <tx:attributes> 
     <tx:method name="saveEmp" propagation="REQUIRED" rollback-for="Exception"/> 
     <tx:method name="*"/> 
    </tx:attributes> 
</tx:advice> 
<aop:config> 
    <aop:pointcut id="testServiceOperation" expression="execution(*com.test.service.*(..))"/> 
    <aop:advisor advice-ref="txAdvice" pointcut-ref="testServiceOperation"/> 
    </aop:config> 

Używam org.springframework.orm.hibernate3.HibernateTransactionManager dla transactionManager. Czy to jest poprawne ?


Updated

Stworzyłem moją klasę wyjątku myRuntimeExp rozciągający się od RuntimeException i rzucanie tego samego od metody Dao sposobu użytkowania. ale wciąż nie następuje wycofywanie.Wątpię, czy poprawnie podałem konfiguracje w pliku applnContext.xml. Czy ktoś może mi pomóc, w jaki sposób sprawdzić, czy porady/adnotacje dotyczące transakcji są stosowane do tej metody, czy nie? Czy jest jakiś sposób na uruchomienie go w trybie debugowania i sprawdzić

problem:

używałem

session = getHibernateTemplate().getSessionFactory().openSession(); 

Ale to powinno być bieżącej sesji i to działa dobrze.

session = getHibernateTemplate().getSessionFactory().getCurrentSession(); 

Odpowiedz

4

Jeśli używasz deklaratywny zarządzanie transakcjami, można stracić większość tego boilerplate:

TestDaoImpl:

private SessionFactory sessionFactory; 

public void setSessionFactory(SessionFactory f){ 
    this.sessionFactory = f; 
} 

public void saveOrUpdate(BaseDomainModel baseObject) { 
    Session session = sessionFactory.getCurrentSession(); 
    session.saveOrUpdate(baseObject); 
} 

I można kontrolować transakcję magazynowe z warstwy usług z wykorzystaniem @Transactional (lub XML konfiguracja)

TestServiceImpl:

private TestDao testDao; 

public void setTestDao(TestDao d){ 
    this.testDao = d; 
} 

@Transactional // one transaction for multiple operations 
public void someServiceMethod(Collection<BaseDomainModel> data){ 
    for(BaseDomainModel baseObject : data) 
     testDao.saveOrUpdate(baseObject); 
} 

odniesienia:

1

Możesz umieścić parametr sessionFactory w TestServiceImpl i otworzyć tam sesję.

+0

Czy pomoc w ramach wiosennej deklaracji transakcji jest w tym przypadku pomocna? – Vaandu

+0

tak, oczywiście, zadeklaruj, że transakcja jest potrzebna na dao ORAZ na poziomie usługi. Jeśli dao wykryje, że usługa otworzyła transakcję, użyje jej zamiast tworzyć nową transakcję. – nanda

+0

Nie zgadzam się, transakcje powinny być potrzebne w odniesieniu do metod usług, a nie metod dao. W ten sposób wywołanie usługi może być atomowe, nawet jeśli używa wielu metod dao (tak, wiem, że możesz to również osiągnąć, łącząc istniejące transakcje, ale wolę czysty rozdział warstw) –

4

domyślnie Spring tylko rolki z powrotem do niekontrolowanej wyjątku. Musisz podać cofnięcie - dlaattribute i określić wyjątek, który próbujesz przechwycić.


Od wiosny documentation:

Należy jednak pamiętać, że transakcja kod infrastruktura Ramowa wiosna będzie domyślnie zaznaczyć tylko transakcję za wycofywania w przypadku wykonywania, niezaznaczone wyjątki; to znaczy, gdy zgłoszony wyjątek jest instancją lub podklasą RuntimeException. (Błędy będzie również - domyślnie -. Skutkują rollback) sprawdzone wyjątki, które są wyrzucane z metody transakcyjnej będzie nie wynik w transakcji są wycofywane.

+0

, należy również dodać: virgium03

+0

@ virgium03 - Dzięki. możesz zobaczyć powyższy xml snipper gdzie podałem . To powinno wystarczyć - czy mam rację? – Vaandu

+0

można również zmienić poziom rejestrowania na debugowanie i zobaczyć, kiedy transakcje są zatwierdzane, wycofywane itp. – virgium03

2

Tutaj dostać te fragmenty i mamy nadzieję, będą one pomóc:

<bean id="abstractService" 
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" 
abstract="true"> 
<property name="transactionManager" ref="transactionManager" /> 
<property name="transactionAttributes"> 
    <props> 
     <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> 
     <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop> 
     <prop key="update*">PROPAGATION_REQUIRED, -Exception</prop> 
     <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop> 
     <prop key="delete*">PROPAGATION_REQUIRED, -Exception</prop> 
     <prop key="save*">PROPAGATION_REQUIRED, -Exception</prop> 
    </props> 
</property> 
</bean> 

<bean id="persistenceServiceTarget" class="com.blahblah.server.service.impl.PersistenceServiceImpl"> 
<property name="persistenceDAO" ref="persistenceDAO" /> 
</bean> 
<bean id="persistenceService" parent="abstractService"> 
    <property name="target" ref="persistenceServiceTarget" /> 
</bean> 

<tx:annotation-driven transaction-manager="transactionManager" /> 

<bean id="abstractDAO" 
class="org.springframework.orm.hibernate3.support.HibernateDaoSupport" 
abstract="true"> 
<property name="sessionFactory"> 
    <ref bean="webSessionFactory" /> 
</property> 
</bean> 

<bean id="persistenceDAO" class="com.blahblah.server.dao.impl.PersistenceDAOImpl" 
parent="abstractDAO"> 
</bean> 

Te powinny być rzeczy, które potrzebujesz. Nie muszą być w tym samym pliku, może podzielić je między usługi i daos.

1

Kolejnym punktem jest sprawdzenie, czy baza danych obsługuje transakcję.

Powiązane problemy